Java多线程生产者与消费者等待唤醒机制(示例)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/dfBeautifulLive/article/details/81739040

在下面新建的两条线程,两条线程操作的对象都是学生类,一条线程生产学生对象的数据,一条线程消费学生对象的数据,且做到,有数据才消费,没数据就等待,没数据就生产,有数据就等待。

第一个案例是学生类对象,非常的简单就定义了两个成员变量,以及一个用于唤醒线程的标记。

成员变量默认会赋值,生命周期随着对象的产生而产生,随着对象的销毁而销毁,成员变量存储在堆中

静态变量就是类变量,随着类的产生而产生,随着类的销毁而销毁

局部变量,方法体,或参数,随着方法产生或销毁,分配在栈内存中

​public class Student {
    public String name;
    public int age;
    boolean flag; //默认情况是false--->没有数据,如果是true说明有数据。
}
​

下面的是生产者学生对象的demo

在构造方法中传递了学生对象,保证生产者与消费者操作的是同一个对象。

wait:释放资源,释放锁,object的方法,用在同步锁中,以锁控制线程

wait(),notify(),notifyAll()方法是用在同步当中的:必须是同步当中的同一把锁操作线程。

package secondDemo;

/**
 * Created by df on 2018/8/16.
 */
public class setThread implements Runnable {
    private Student s;
    int x = 0;

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

    @Override
    public void run() {
        while (true) {
            synchronized (s) {
                //唤醒机制,生产者,先判断有没有数据,有数据等待消费,没数据就生产数据
                if (s.flag) {
                    try {
                        s.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                //flag为false 执行以下代码
                if (x % 2 == 0) {
                    s.name = "java";
                    s.age = 25;
                } else {
                    s.name = "android";
                    s.age = 20;
                }
                x++;
                //数据生产一次  修改标记为true,有了数据生产数据的线程就等待
                s.flag=true;
                //唤醒线程
                s.notify();
            }
        }
    }
}

下面的是学生对象的消费者模式demo

 在构造方法中传递了学生对象,保证生产者与消费者操作的是同一个对象。

package secondDemo;

/**
 * Created by df on 2018/8/16.
 */
public class getThread implements Runnable {
    private Student s;

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

    @Override
    public void run() {
        while (true) {
            synchronized (s) {
                //消费者 有数据就消费,没数据就等待数据被生产
                if (!s.flag) {
                    try {
                        s.wait();//在等待的时候立即释放锁,方便其他的线程使用锁。而且被唤醒时,就在此处唤醒,
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                // flag--->true:消费数据
                System.out.println(s.name + "  ====   " + s.age);
                // 消费完毕后,数据没有了,修改标记
                s.flag = false;
                // 唤醒线程
                //唤醒并不代表你立即可以得到执行权,此时仍然需要抢CPU的执行权,
                s.notify();
            }
        }
    }
}

下面的是测试用例,就是简单的创建了两条线程,然后启动刚才的生产者与消费者

  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();

    }

最后就是执行完毕的结果

猜你喜欢

转载自blog.csdn.net/dfBeautifulLive/article/details/81739040