等待唤醒机制,生产者消费者

测试类

package com.shujia.day19.waitdemo;

/*
    等待唤醒机制:
        共享数据:学生对象(name,age)
        生产者线程:对学生对象进行赋值操作
        消费者线程:对学生对象进行取值操作


    为了观察更好的效果,我们可以让生产者赋值不同的信息
    这时候出现了重复取值和姓名与年龄对应不上的情况
    检测线程程序是否存在安全问题的三要素:
        1、是否存在多线程环境?是 生产者和消费者
        2、是否存在共享数据?是 student
        3、是否存在多条语句操作共享数据?是

    解决方案:
        1、加入同步代码块
        2、加入lock锁

    虽然解决了线程安全的问题,但是结果并不是我们想要的结果,在生产者消费者模型中,消费一次应该通知生产者生产。等待唤醒机制。
    注意:等待唤醒机制是建立线程安全的基础之上设置的。


 */
public class StudentDemo {
    public static void main(String[] args) {
        Student s = new Student();

        ProductThread p1 = new ProductThread(s);
        ConsumerThread c1 = new ConsumerThread(s);
        p1.start();
        c1.start();
    }
}

生产者类

package com.shujia.day19.waitdemo;

public class ProductThread extends Thread{
    private Student s;
    private int i = 0;

    public ProductThread(Student s) {
        this.s = s;
    }

    @Override
    public void run() {
        while (true){
            try {
                Thread.sleep(30);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (s){
                //应该先看一看数据有没有被消费,若被消费了,才赋新的值,通知消费者消费,若没有消费,等待消费者消费
                if(s.getFlag()){
                    //若学生对象中flag成员变量值是true,生产就不会生产
                    //由多个线程共享且唯一的锁对象进行等待
                    try {
                        s.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                if(i%2==0){
                    s.setName("魏一民");
                    s.setAge(19);
                }else {
                    s.setName("陈真");
                    s.setAge(18);
                }
                i++;
                s.setFlag(true);
                //赋值之后应该通知消费者进行消费数据
                s.notify();
            }
        }

    }
}

消费者类

package com.shujia.day19.waitdemo;

public class ConsumerThread extends Thread {
    private Student s;

    public ConsumerThread(Student s) {
        this.s = s;
    }

    @Override
    public void run() {
//        Student s = new Student();
        while (true) {
            try {
                Thread.sleep(30);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (s) {
                //消费者消费数据之前,先判断数据有没有生产,若生产了,就取值打印,若没有生产,就等待,通知生产者生产
                if (!s.getFlag()) {
                    try {
                        s.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                System.out.println(s.getName() + "-" + s.getAge());
                s.setFlag(false);
                //通知生产者赋值新的数据
                s.notify();
            }
        }
    }
}

学生类

package com.shujia.day19.waitdemo;

public class Student {
    private String name;
    private int age;
    private boolean flag; // boolean类型的默认值在内存是false

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public boolean getFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
posted @ 2024-08-19 22:15  ていせい  阅读(4)  评论(0编辑  收藏  举报