经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Java » 查看文章
Java并发(二十一)----wait notify介绍
来源:cnblogs  作者:|旧市拾荒|  时间:2023/12/26 9:50:05  对本文有异议

1、小故事 - 为什么需要 wait

  • 由于条件不满足(没烟干不了活啊,等小M把烟送过来),小南不能继续进行计算

  • 但小南如果一直占用着锁,其它人就得一直阻塞,效率太低

  • 于是老王单开了一间休息室(调用 wait 方法),让小南到休息室(WaitSet)等着去了,但这时锁释放开,其它人可以由老王随机安排进屋

  • 直到小M将烟送来,大叫一声 [ 你的烟到了 ] (调用 notify 方法)

  • 小南于是可以离开休息室,重新进入竞争锁的队列

2、wait notify 原理

  • Owner 线程发现条件不满足,调用 wait 方法,即可进入 WaitSet 变为 WAITING 状态

  • BLOCKED 和 WAITING 的线程都处于阻塞状态,不占用 CPU 时间片

  • BLOCKED 线程会在 Owner 线程释放锁时唤醒

  • WAITING 线程会在 Owner 线程调用 notify 或 notifyAll 时唤醒,但唤醒后并不意味者立刻获得锁,仍需进入 EntryList 重新竞争

3、API 介绍

  • obj.wait() 让进入 object 监视器的线程到 waitSet 等待

  • obj.notify() 在 object 上正在 waitSet 等待的线程中挑一个唤醒

  • obj.notifyAll() 让 object 上正在 waitSet 等待的线程全部唤醒

它们都是线程之间进行协作的手段,都属于 Object 对象的方法。必须获得此对象的锁,才能调用这几个方法,否则会报IllegalMonitorStateException

  1. final static Object obj = new Object();
  2. ?
  3. public static void main(String[] args) {
  4. ?
  5.    new Thread(() -> {
  6.        synchronized (obj) {
  7.            log.debug("执行....");
  8.            try {
  9.                obj.wait(); // 让线程在obj上一直等待下去
  10.           } catch (InterruptedException e) {
  11.                e.printStackTrace();
  12.           }
  13.            log.debug("其它代码....");
  14.       }
  15.   }).start();
  16. ?
  17.    new Thread(() -> {
  18.        synchronized (obj) {
  19.            log.debug("执行....");
  20.            try {
  21.                obj.wait(); // 让线程在obj上一直等待下去
  22.           } catch (InterruptedException e) {
  23.                e.printStackTrace();
  24.           }
  25.            log.debug("其它代码....");
  26.       }
  27.   }).start();
  28. ?
  29.    // 主线程两秒后执行
  30.    sleep(2);
  31.    log.debug("唤醒 obj 上其它线程");
  32.    synchronized (obj) {
  33.        obj.notify(); // 唤醒obj上随机一个线程
  34.        // obj.notifyAll(); // 唤醒obj上所有等待线程
  35.   }
  36. }

notify 的一种结果

  1. 20:00:53.096 [Thread-0] c.TestWaitNotify - 执行....
  2. 20:00:53.099 [Thread-1] c.TestWaitNotify - 执行....
  3. 20:00:55.096 [main] c.TestWaitNotify - 唤醒 obj 上其它线程
  4. 20:00:55.096 [Thread-0] c.TestWaitNotify - 其它代码....

notifyAll 的结果

  1. 19:58:15.457 [Thread-0] c.TestWaitNotify - 执行....
  2. 19:58:15.460 [Thread-1] c.TestWaitNotify - 执行....
  3. 19:58:17.456 [main] c.TestWaitNotify - 唤醒 obj 上其它线程
  4. 19:58:17.456 [Thread-1] c.TestWaitNotify - 其它代码....
  5. 19:58:17.456 [Thread-0] c.TestWaitNotify - 其它代码....

wait() 方法会释放对象的锁,进入 WaitSet 等待区,从而让其他线程就机会获取对象的锁。无限制等待,直到 notify 为止

wait(long n) 有时限的等待, 到 n 毫秒后结束等待,或是被 notify

 

原文链接:https://www.cnblogs.com/xiaoyh/p/17157922.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号