Java线程中的wait、notify和notifyAll解析

时间:2022-12-27 14:01:06

等待唤醒案例:线程间的通信

Java线程中的wait、notify和notifyAll解析 顾客去包子铺买包子,告知老板自身需求后,进入等待(调用wait()方法)老板处理的过程,此时顾客的状态为 WAITING,老板做好包子后,告知(调用notify()方法)顾客包子做好了。 ????线程间的通信的主要思想是生产者消费者机制。

代码实现

思路如下:

  1. 创建一个顾客线程(消费者):告知老板要的包子的种类和数量,调用wait方法,放弃CPU的执行,进入到WAITING状态(无限等待)
  2. 创建一个老板线程(生产者):花了5秒做包子,做好包子之后,调用notify方法,唤醒顾客吃包子。

代码如下: 定义一个锁对象:

//创建锁对象,保证唯一
Object obj = new Object();

创建一个顾客线程(消费者):

// 创建一个顾客线程(消费者)
new Thread(){
    @Override
    public void run() {
        //一直等着买包子
        while(true){
            //保证等待和唤醒的线程只能有一个执行,需要使用同步技术
            synchronized (obj){
                System.out.println("顾客告知老板要的包子的种类和数量");
                //调用wait方法,放弃cpu的执行,进入到WAITING状态(无限等待)
                try {
                    obj.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //唤醒之后执行的代码
                System.out.println("包子已经做好了,开吃!");
                System.out.println("---------------------------------------");
            }
        }
    }
}.start();

创建一个老板线程(生产者):

//创建一个老板线程(生产者)
new Thread(){
    @Override
    public void run() {
        //一直做包子
        while (true){
            //花了5秒做包子
            try {
                Thread.sleep(5000);//花5秒钟做包子
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            //保证等待和唤醒的线程只能有一个执行,需要使用同步技术
            synchronized (obj){
                System.out.println("老板5秒钟之后做好包子,告知顾客,可以吃包子了");
                //做好包子之后,调用notify方法,唤醒顾客吃包子
                obj.notify();
            }
        }
    }
}.start();

输出如下:

顾客告知老板要的包子的种类和数量 老板5秒钟之后做好包子,告知顾客,可以吃包子了 包子已经做好了,开吃!

顾客告知老板要的包子的种类和数量 老板5秒钟之后做好包子,告知顾客,可以吃包子了 包子已经做好了,开吃!

????注意: 顾客和老板线程必须使用同步代码块包裹起来,保证等待和唤醒只能有一个在执行 同步使用的锁对象必须保证唯一 只有锁对象才能调用wait和notify方法。

扩展:Object类中wait带参方法和notifyAll方法

进入到TimeWaiting(计时等待)有两种方式

  1. 使用sleep(long m)方法,在毫秒值结束之后,线程睡醒进入到Runnable/Blocked状态
  2. 使用wait(long m)方法,wait方法如果在毫秒值结束之后,还没有被notify唤醒,就会自动醒来,线程睡醒进入到Runnable/Blocked状态

唤醒的方法:

  • void notify() 唤醒在此对象监视器上等待的单个线程。
  • void notifyAll() 唤醒在此对象监视器上等待的所有线程。

本文内容到此结束了, 如有收获欢迎点赞????收藏????关注✔️,您的鼓励是我最大的动力。 如有错误❌疑问????欢迎各位大佬指出。 主页共饮一杯无的博客汇总????‍????

保持热爱,奔赴下一场山海。????????????