✨个人主页:bit me👇 ✨当前专栏:Java EE初阶👇 ✨每日一语:阅己,越己,悦己;自行,自省,自醒;无味,无谓,无畏。 目 录
✨个人主页:bit me👇
✨当前专栏:Java EE初阶👇
✨每日一语:阅己,越己,悦己;自行,自省,自醒;无味,无谓,无畏。
由于线程之间是抢占式执行的, 因此线程之间执行的先后顺序难以预知. 但是实际开发中有时候我们希望合理的协调多个线程之间的执行先后顺序.
wait 和 notify 相比于 join 能更好的控制线程之间的执行顺序
注意: wait, notify都是 Object 类的方法.
- 使用 o1.notify() 就可以唤醒调用 o1.wait 的线程!!
- 使用 o2.notify() 是不可以唤醒调用 o1.wait 的线程!
对于 wait 来说,内部的执行过程还有点小麻烦
wait 一上来就得释放锁,,得在调用 wait 之前,先拿到锁,
wait 必须要放到 synchronized 中使用,synchronized 加锁的对象必须是和调用 wait 方法的对象是同一个对象,还得和调用 notify 的对象是同一个对象!!!
等待通知
当通知到达之后,就会被唤醒,并且尝试重新获取锁
wait 结束等待的条件:
代码示例: 观察wait()方法使用
public class Demo17 { public static void main(String[] args) throws InterruptedException { Object object = new Object(); synchronized (object) { System.out.println("wait 之前"); object.wait(); System.out.println("wait 之后"); } }}
notify 方法是唤醒等待的线程
举例实现 wait 和 notify 的内部执行过程:创建两个线程 一个线程调用 wait,一个线程调用 notify
public class Demo18 {//这个对象用来做锁对象public static Object locker = new Object();public static void main(String[] args) { //用来取等待 Thread waitTask = new Thread(()->{ synchronized (locker) { try { System.out.println("wait 开始"); locker.wait(); System.out.println("wait 结束"); } catch (InterruptedException e) { e.printStackTrace(); } } }); waitTask.start(); //创建一个用来通知 / 唤醒的线程 Thread notifyTask = new Thread(()->{ //让用户来控制,用户输入某个内容之后,再执行通知 Scanner scanner = new Scanner(System.in); System.out.println("输入任意内容,开始通知:"); //next 会阻塞,直到用户真正输入内容以后 scanner.next(); synchronized (locker){ System.out.println("notify 开始"); locker.notify(); System.out.println("notify 结束"); } }); notifyTask.start();}}
执行过程及结果:
线程 1 需要先计算一个结果,线程 2 来使用这个结果,线程 2 就可以 wait ,线程 1 计算完结果之后,notify ,唤醒线程 2。
wait 和 notify 机制,还能有效避免 "线程饿死"。
(有些情况下,调度器可能分配不均匀,导致有些线程反复占用 CPU,有些线程始终捞不着 CPU)例如:
多个线程抢占一个锁,一个线程 A 抢到了,其他线程排队等待,但是抢到锁的线程 A 却无法完成任务,占着锁不放,导致其他锁也不能干活儿,于是这个线程 A 决定释放锁出来,在外面等待,给其他的锁一些机会,由于线程之间在系统里的调度是随机的,可能下次又是线程 A 进来了,于是多次情况下都是线程 A 占用了 CPU,其他线程都碰不到,导致线程饿死,旱的旱死,涝的涝死。
因此使用 wait 和 notify 就可以解决上述问题,让后面的多个线程拿到锁之后判定当前任务是否可以执行,如果能就干活,不能就进行 wait !wait 来等待合适的时候(条件满足)再继续执行 / 再参与竞争锁
拓展:
这三个阻塞的状态,都会导致 PCB 进入内核队列中对应的阻塞队列。操作系统内核是不区分这三个的状态的!这三个状态是 JVM 中的状态,操作系统内核中衡量线程的状态是另外的方式,没有 JVM 里面的这么细。
notify方法只是一次唤醒某一个等待线程. 使用notifyAll方法可以一次唤醒所有的等待线程.
其实理论上 wait 和 sleep 完全是没有可比性的,因为一个是用于线程之间的通信的,一个是让线程阻塞一段时间,唯一的相同点就是都可以让线程放弃执行一段时间
他们俩都会让线程进入阻塞,阻塞的原因和目的不同,进入的状态也不同,被唤醒的条件也不一样。
实际开发中会很少使用 sleep ,目的是为了 “放权” ,暂时让出当前 CPU 的使用权。之所以 sleep 使用的少,等待的时间太固定了,要是有突发情况想提前唤醒并不是那么容易,wait 就用的比较多了,wait 可以进行死等,也能设置最长等待时间(涵盖了 sleep 的功能)
1. wait 需要搭配 synchronized 使用. sleep 不需要.
2. wait 是 Object 的方法 sleep 是 Thread 的静态方法.
来源地址:https://blog.csdn.net/m0_67660672/article/details/129505822
--结束END--
本文标题: wait 和 notify
本文链接: https://lsjlt.com/news/414574.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-04-01
2024-04-03
2024-04-03
2024-01-21
2024-01-21
2024-01-21
2024-01-21
2023-12-23
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0