JavaEE多线程基础---wait和notify


🥀wait和notify

线程很讨厌的一点,抢占式执行
调度的过程是随机的~~
很多时候,我们希望多个线程按照一个预期的顺序来进行执行 ~

wait notify 就是来调配线程执行顺序的~

线程执行到wait,就会发生阻塞~~
直到另一个线程,调用notify 把这个wait唤醒~ 才会继续往下走~

监视器,此处特指的是 synchronized ~ synchronized 也叫做监视器锁

在这里插入图片描述

1.wait()方法

wait操作,内部本质上,做了三件事 :

1.释放当前锁(保证其他线程能够正常往下运行)~
2.进行等待通知
3.满足一定条件的时候(别人调用notify),被唤醒,然后尝试重新获取锁

等待通知的前提是要先释放锁,而释放锁的前提,是你得加了锁(加上锁,才能谈释放)
脱离 synchronized 使用 wait 会直接抛出异常!

wait 结束等待的条件:

  • 其他线程调用该对象的 notify 方法.
  • wait 等待时间超时 ( wait 方法提供一个带有 timeout 参数的版本, 来指定等待时间).
  • 其他线程调用该等待线程的 interrupted 方法, 导致 wait 抛出 InterruptedException 异常.

👀观察wait()方法使用:
在这里插入图片描述
因为没有调用notify(),所以线程一直处于阻塞状态~

在这里插入图片描述

2.notify()方法

notify 方 法 是 唤 醒 等 待 的 线 程 ❕

在这里插入图片描述

  • 方法notify()也要在同步方法或同步块中调用,该方法是用来通知那些可能等待该对象的对象锁的其它线程,对其发出通知,并使它们重新获取该对象的对象锁。
  • 如果有多个线程等待,则有线程调度器随机挑选出一个呈 wait 状态的线程。(并没有 “先来后到”)
  • notify()方法后,当前线程不会马上释放该对象锁,要等到执行notify()方法的线程将程序执行完,也就是退出同步代码块之后才会释放对象锁。

👀观察notify()方法使用:

  public static void main(String[] args) {
        Object object = new Object();
        Thread thread = new Thread(()-> {
            synchronized (object) {
                System.out.println("wait之前");
                try {
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("wait 之后");
            }
        });

        Thread thread1 = new Thread(()-> {
            synchronized (object) {
                System.out.println("notify 之前");
                object.notify();
                System.out.println("notify 之后");
            }
        });

        thread.start();
        thread1.start();

    }

在这里插入图片描述
要保证加锁的对象和调用wait的对象得是同一个对象,还要保证,调用的wait对象和调用notify的对象也是同一个对象~~

a.wait();
b.notify()

💔上述代码是无法唤醒await的!!!

如果线程1先调用了wait,线程2后调用notify,此时notify会唤醒wait
如果线程2先调用了notify,线程1后执行了wait,此时就会错过唤醒wait !(但如果没人wait,调用notify()没有副作用)

❗ 所以编写代码的时候要考虑notify是否会在wait之前执行的情况,防止wait没人唤醒,导致一直等待~

wait/notify 控制多线程之间的执行先后顺序~
🥩总结:

  1. 都要搭配synchronized来进行使用
  2. 得使用同一个对象,才是有效的
  3. 用来加锁的对象和wait / notify对象也得一致
  4. 即使当前没有线程在wait,直接notify也不会有副作用

在这里插入图片描述

3.notifyAll()方法

多个线程都在wait的话,notify是随机唤醒一个~
notifyAll则是全部唤醒!!
但很少用到~
因为即使唤醒了所有的wait,这些wait又需要重新竞争锁,重新竞争锁的过程仍然是单行的~~

在这里插入图片描述

4.sleep和wait的对比

都是让线程进入阻塞等待的状态
sleep是通过时间来控制何时唤醒的~~
wait则是由其他线程通过notify来唤醒的~

wait还有一个重载版本,参数可以传时间,表示等待的最大时间(类似于join)

总结

在这里插入图片描述

你可以叫我哒哒呀
本篇到此结束
“莫愁千里路,自有到来风。”
我们顶峰相见!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值