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

final static Object obj = new Object();

public static void main(String[] args) {

   new Thread(() -> {
       synchronized (obj) {
           log.debug("执行....");
           try {
               obj.wait(); // 让线程在obj上一直等待下去
          } catch (InterruptedException e) {
               e.printStackTrace();
          }
           log.debug("其它代码....");
      }
  }).start();

   new Thread(() -> {
       synchronized (obj) {
           log.debug("执行....");
           try {
               obj.wait(); // 让线程在obj上一直等待下去
          } catch (InterruptedException e) {
               e.printStackTrace();
          }
           log.debug("其它代码....");
      }
  }).start();

   // 主线程两秒后执行
   sleep(2);
   log.debug("唤醒 obj 上其它线程");
   synchronized (obj) {
       obj.notify(); // 唤醒obj上随机一个线程
       // obj.notifyAll(); // 唤醒obj上所有等待线程
  }
}

notify 的一种结果

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

notifyAll 的结果

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

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

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

Java并发(二十一)----wait notify介绍的更多相关文章

  1. Java并发(十一):Condition条件

    先做总结: 1.为什么使用Condition条件? synchronized配合Object的wait().notify()系列方法可以实现等待/通知模式. Lock提供了条件Condition,对线 ...

  2. 006 Java并发编程wait、notify、notifyAll和Condition

    原文https://www.cnblogs.com/dolphin0520/p/3920385.html#4182690 Java并发编程:线程间协作的两种方式:wait.notify.notifyA ...

  3. Java并发(二):基础概念

    并发编程的第二部分,先来谈谈发布(Publish)与逸出(Escape); 发布是指:对象能够在当前作用域之外的代码中使用,例如:将对象的引用传递到其他类的方法中,对象的引用保存在其他类可以访问的地方 ...

  4. Java并发包下锁学习第二篇Java并发基础框架-队列同步器介绍

    Java并发包下锁学习第二篇队列同步器 还记得在第一篇文章中,讲到的locks包下的类结果图吗?如下图: ​ 从图中,我们可以看到AbstractQueuedSynchronizer这个类很重要(在本 ...

  5. Java并发:ThreadLocal的简单介绍

    作者:汤圆 个人博客:javalover.cc 前言 前面在线程的安全性中介绍过全局变量(成员变量)和局部变量(方法或代码块内的变量),前者在多线程中是不安全的,需要加锁等机制来确保安全,后者是线程安 ...

  6. Java 并发专题 : Executor详细介绍 打造基于Executor的Web服务器

    转载标明出处:http://blog.csdn.net/lmj623565791/article/details/26938985 继续并发,貌似并发的文章很少有人看啊~哈~ 今天准备详细介绍java ...

  7. Java 并发专题 : Executor具体介绍 打造基于Executor的Webserver

    转载标明出处:http://blog.csdn.net/lmj623565791/article/details/26938985 继续并发,貌似并发的文章非常少有人看啊~哈~ 今天准备具体介绍jav ...

  8. 菜鸟学Java(二十一)——怎样更好的进行单元測试——JUnit

    測试在软件生命周期中的重要性,不用我多说想必大家也都很清楚.软件測试有许多分类,从測试的方法上可分为:黑盒測试.白盒測试.静态測试.动态測试等:从软件开发的过程分为:单元測试.集成測试.确认測试.验收 ...

  9. Java并发编程-volatile可见性的介绍

    要学习好Java的多线程,就一定得对volatile关键字的作用机制了熟于胸.最近博主看了大量关于volatile的相关博客,对其有了一点初步的理解和认识,下面通过自己的话叙述整理一遍. 有什么用? ...

  10. 菜鸟学Java(二十一)——如何更好的进行单元测试——JUnit

    测试在软件生命周期中的重要性,不用我多说想必大家也都非常清楚.软件测试有很多分类,从测试的方法上可分为:黑盒测试.白盒测试.静态测试.动态测试等:从软件开发的过程分为:单元测试.集成测试.确认测试.验 ...

随机推荐

  1. 月工资不到10元的内容审核专员? - ChatGPT 在内容自动审查中的应用

    内容过滤筛查是指对网络上发布或传播的文本.图片.视频等内容进行审核和监管,以防止出现违法违规.暴力色情.虚假广告.电信诈骗等现象,维护网络安全和社会秩序. 内容过滤筛查是一个亟待解决的问题,因为网络内 ...

  2. Web组态可视化软件之BY组态可视化平台介绍

    Web组态可视化软件之BY组态可视化平台介绍 关于组态软件,首先要从组态的概念开始说起. 什么是组态 组态(Configure)的概念来自于20世纪70年代中期出现的第一代集散控制系统(Distrib ...

  3. AI在人才测评领域的应用情况概述

    目录 收起 一.AI技术的通俗理解 二.AI在人才测评领域的应用情况概述 三.AI在构建人才标准上的应用 1.人才标准构建 2.人才画像 3.人岗智能匹配 四.AI在人才测评实施方面的应用 1.AI面 ...

  4. 11. 用Rust手把手编写一个wmproxy(代理,内网穿透等), 实现健康检查

    11. 用Rust手把手编写一个wmproxy(代理,内网穿透等), 实现健康检查 项目 ++wmproxy++ gite: https://gitee.com/tickbh/wmproxy gith ...

  5. 01--OpenStack 手动安装手册(Icehouse)

    #OpenStack 手动安装手册(Icehouse) 声明:本博客欢迎转发,但请保留原作者信息!作者:[罗勇] 云计算工程师.敏捷开发实践者博客:http://yongluo2013.github. ...

  6. Java-全网最详细反射

    Java-反射 前言 Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象 ...

  7. Pushpin:开源即时通信神器,让你的API秒变实时API,轻松实现WebSocket,HTTP流和HTTP长轮询等服务

    作为一个开发者,你可能已经利用过REST API来构建和集成各种应用.REST API是基于HTTP协议的交互模式,它使得客户端和服务器可以通过请求和响应来进行数据交换,简单.灵活.通用. 然而,当你 ...

  8. 【不限框架】超好用的3d开源图片预览插件推荐

    今天给大家推荐一款超好用的图片预览插件-image-preview 简单说明 image-preview是一款主要面向移动端web应用,同时兼容pc,基于原生js,不限框架,react,vue,ang ...

  9. 阿里云创建BUCKET脚本

    创建BUCKET脚本 安装模块 pip install pymysql pip install aliyun-python-sdk-core pip install aliyun-python-sdk ...

  10. [学习笔记]TypeScript查缺补漏(一):类

    @ 目录 基础知识 创建类型 类的初始化 类型和值 JSDoc 注释 字段 私有字段 可选和非可选字段 字段类型约束 Getter/Setter 静态成员 函数重载 构造函数 参数属性 类的实例化 箭 ...