• 【线程间通信:等待唤醒机制】


    在线程安全解决之后,还是一样存在着如下的问题:

    A:如果消费者先抢到CPU的执行权,就会去消费数据,但是现在的数据是默认值,没有意义,应该等着数据有意义,再消费。

    B:如果生产者先抢到CPU的执行权,就会去生产数据,但是呢,它生产完数据后,还继续拥有执行权,它又继续产生数据。这是有问题的,它应该等着消费者把数据消费掉,然后再生产。

    正常的思路:

    A:生产者:先看是否有数据,有就等待,没有就生产,生产完后通知消费者来消费数据。

    B:消费者:先是是否有数据,有就消费,没有就等待,通知生产者生产数据。

    为了处理这样的问题,JAVA就提供了一种机制,等待唤醒机制。

    等待唤醒: Object 类中提供了三个方法:

      wait():等待

      notify():唤醒单个线程

      notifyAll():唤醒所有线程

    为什么这些方法不定义在Thread类中呢?

      这些方法的调用必须通过锁对象调用,要所有锁对象都可以调用的话,方法就应该在他们共有的父类上,也就是Object类。

    例子:线程间通信:生产者消费者(等待唤醒机制)

    package com.test;
    
    public class Student {
    
        String name;
        int age;
        boolean isTrue;
    
        public synchronized void set(String name, int age) {
            /**如果有数据,就等待*/
            if (this.isTrue) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            /**设置数据*/
            this.name = name;
            this.age = age;
            /**修改标记*/
            this.isTrue = true;
            this.notify();
        }
    
        public synchronized void get() {
             /**如果没有数据,就等待*/
            if (!this.isTrue) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
             /**获取数据*/
            System.out.println(this.name + "---" + this.age);
             /**修改标记*/
            this.isTrue = false;
            this.notify();
        }
    
    }
    package com.test;
    
    public class SetThread implements Runnable {
    
        private Student s;
        private int x = 0;
    
        public SetThread(Student s) {
            this.s = s;
        }
    
        @Override
        public void run() {
            while (true) {
    
                if (x % 2 == 0) {
                    s.set("叶胖子", 27);
                } else {
                    s.set("王瘦子", 31);
                }
                x++;
    
            }
        }
    }
    package com.test;
    
    public class GetThread implements Runnable {
    
        private Student s;
    
        public GetThread(Student s){
            this.s = s;
        }
    
        @Override
        public void run() {
            while (true){
                s.get();
            }
        }
    
    }
    package com.test;
    
    public class StudentTest {
    
        public static void main(String[] args) {
    
            Student s = new Student();
    
            SetThread st = new SetThread(s);
            GetThread gt = new GetThread(s);
    
            Thread t1 = new Thread(st);
            Thread t2 = new Thread(gt);
    
            t1.start();
            t2.start();
    
        }
    
    }
    终身学习者
  • 相关阅读:
    迭代器求迄今为止所有的闰年
    记录列表中每个元素被访问的次数
    访问修改属性日志
    描述符
    摄氏与华氏转变
    【bzoj1925】[Sdoi2010]地精部落 组合数学+dp
    【bzoj1280】Emmy卖猪pigs 最大流
    【bzoj1449/bzoj2895】[JSOI2009]球队收益/球队预算 费用流
    【bzoj2721】[Violet 5]樱花 数论
    【bzoj4810】[Ynoi2017]由乃的玉米田 莫队算法+STL-bitset
  • 原文地址:https://www.cnblogs.com/zuixinxian/p/9574749.html
Copyright © 2020-2023  润新知