wait、notify、notifyAll的阻塞和恢复
前言:昨天尝试用Java自行实现生产者消费者问题(Producer-Consumer Problem),在coding时,使用到了Condition的await和signalAll方法,然后顺便想起了wait和notify,在开发中遇到了一个问题:wait、notify等阻塞和恢复的时机分别是什么?在网上Google了很久各种博文后,发现几乎没有人提到这个点。最后在官方文档中才找到了相应的介绍。
(一)准备
按照惯例应该是要先介绍一下wait、notify和notifyAll的基础知识。我找到了一篇不错的文章:《Java的wait(), notify()和notifyAll()使用小结》,它甚至介绍了为什么wait等方法为什么必须先获得对象锁。在这里我就不重复说了。
(二)阻塞和恢复
(1)wait方法
wait方法继承自Object类(方法修饰符为fianl native,这也解释了为什么condition类中不能重写wait等方法),一共有三个方法:

public final void wait(long timeout)
throws InterruptedException public final void wait(long timeout, int nanos)
throws InterruptedException public final void wait()
throws InterruptedException

阻塞:这三个方法的调用都会使当前线程阻塞。该线程将会被放置到对该Object的请求等待队列中,然后让出当前对Object所拥有的所有的同步请求。线程会一直暂停所有线程调度,直到下面其中一种情况发生:
① 其他线程调用了该Object的notify方法,而该线程刚好是那个被唤醒的线程;
② 其他线程调用了该Object的notifyAll方法;
③ 其他对象中断/杀死了该线程;
④ (这种情况,只针对前两个方法)线程在等待指定的时间后;
恢复:线程将会从等待队列中移除,重新成为可调度线程。它会与其他线程以常规的方式竞争对象同步请求。一旦它重新获得对象的同步请求,所有之前的请求状态都会恢复,也就是线程调用wait的地方的状态。线程将会在之前调用wait的地方继续运行下去。
(2)notify和notifyAll方法
notify的作用就是唤醒请求队列中的一个线程,而notifyAll唤醒的是请求队列中的所有线程。
被唤醒的线程不会马上运行,除非获取了该Object的锁。也就是说,调用notify的线程,在调用notify后,不会像wait一样,马上阻塞线程的运行。而是继续运行,直到相应的线程调度完成或者让出Object的锁。而被唤醒的线程会在当前线程让出Object锁后,与其他线程以常规的方式竞争对象锁(正如上面提到的)。
参考资料:
https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html
public class WaitNotifyDemo {
private volatile int val = ;
private Object o1= new Object();
private Object o2= new Object();
public class PrinterA implements Runnable {
public void run() {
while (val <= ) {
synchronized (o2) {
try {
System.out.println("");
o2.wait();
System.out.println("");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class PrinterC implements Runnable {
public void run() {
while (val <= ) {
synchronized (o2) {
try {
System.out.println("");
o2.wait();
System.out.println("");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class PrinterB implements Runnable {
public void run() {
while (val <= ) {
synchronized (o2) {
o2.notify();
// o2.notifyAll();
}
}
}
}
public static void main(String[] args) {
WaitNotifyDemo demo = new WaitNotifyDemo();
demo.doPrint();
}
private void doPrint() {
PrinterA pa = new PrinterA();
Thread a = new Thread(pa);
a.setName("printerA");
a.start();
PrinterC pc = new PrinterC();
Thread c = new Thread(pc);
c.setName("printerC");
c.start();
PrinterB pB = new PrinterB();
Thread b = new Thread(pB);
b.setName("printerA");
b.start();
}
}
wait、notify、notifyAll的阻塞和恢复的更多相关文章
- Java 多线程学习笔记:wait、notify、notifyAll的阻塞和恢复
前言:昨天尝试用Java自行实现生产者消费者问题(Producer-Consumer Problem),在coding时,使用到了Condition的await和signalAll方法,然后顺便想起了 ...
- java 多线程之wait(),notify,notifyAll(),yield()
wait(),notify(),notifyAll()不属于Thread类,而是属于Object基础类,也就是说每个对像都有wait(),notify(),notifyAll()的功能.因为都个对像都 ...
- Java多线程8:wait()和notify()/notifyAll()
轮询 线程本身是操作系统中独立的个体,但是线程与线程之间不是独立的个体,因为它们彼此之间要相互通信和协作. 想像一个场景,A线程做int型变量i的累加操作,B线程等待i到了10000就打印出i,怎么处 ...
- Java多线程学习之wait、notify/notifyAll 详解
1.wait().notify/notifyAll() 方法是Object的本地final方法,无法被重写. 2.wait()使当前线程阻塞,前提是 必须先获得锁,一般配合synchronized 关 ...
- 【java线程系列】java线程系列之线程间的交互wait()/notify()/notifyAll()及生产者与消费者模型
关于线程,博主写过java线程详解基本上把java线程的基础知识都讲解到位了,但是那还远远不够,多线程的存在就是为了让多个线程去协作来完成某一具体任务,比如生产者与消费者模型,因此了解线程间的协作是非 ...
- Object的wait/notify/notifyAll&&Thread的sleep/yield/join/holdsLock
一.wait/notify/notifyAll都是Object类的实例方法 1.wait方法:阻塞当前线程等待notify/notifyAll方法的唤醒,或等待超时后自动唤醒. wait等待其实是对象 ...
- 使用ReentrantLock和Condition来代替内置锁和wait(),notify(),notifyAll()
使用ReentrantLock可以替代内置锁,当使用内置锁的时候,我们可以使用wait() nitify()和notifyAll()来控制线程之间的协作,那么,当我们使用ReentrantLock的时 ...
- java多线程14 :wait()和notify()/notifyAll()
轮询 线程本身是操作系统中独立的个体,但是线程与线程之间不是独立的个体,因为它们彼此之间要相互通信和协作. 想像一个场景,A线程做int型变量i的累加操作,B线程等待i到了10000就打印出i,怎么处 ...
- Java 多线程 线程的五种状态,线程 Sleep, Wait, notify, notifyAll
一.先来看看Thread类里面都有哪几种状态,在Thread.class中可以找到这个枚举,它定义了线程的相关状态: public enum State { NEW, RUNNABLE, BLOCKE ...
随机推荐
- c# 高效读写文件
一.同步读写文件(在并发情况下不会发生文件被占用异常) static void Main(string[] args) { Parallel.For(0, 10000, e => { strin ...
- 64位Linux安装32位向日葵
查看linux系统版本信息如下,可以看出系统为64位. [root@localhost bin]# uname -aLinux localhost.localdomain 3.10.0-327.3.1 ...
- 《JavaScript语言精粹》之函数化
写在前面 看到好多书评和读书笔记都说<JavaScript语言精粹>字字珠玑,名不虚传..当然,要看得懂才行 其实个人认为函数化部分不是很好,举的例子不是十分恰当,之前看不懂是因为被成功误 ...
- memcache(一)概述
概述 memcache是一种支持分布式的缓存系统,基于网络连接(当然它也可以使用localhost)方式完成服务,本身它是一个独立于应用的程序或守护进程(Daemon方式). 本地缓存 memcach ...
- 在console中输出图片
console.log("%c\n ","font-size:81px;background:url('http://www.baidu.com/img/bdlogo.g ...
- [外挂6]在指定位置下棋 SendMessage函数
a.鼠标软件模拟,函数SendMessage b.分析窗口内棋子相对坐标X,Y c.软件模拟点击棋盘坐标x,y处的棋子 ::SendMessage(hwnd,WM_LBUTTOMDOWN,0,YX); ...
- html5之canvas画图
导航 前言 基本知识 绘制矩形 清除矩形区域 圆弧 路径 绘制线段 绘制贝塞尔曲线 线性渐变 径向渐变(发散) 图形变形(平移.旋转.缩放) 矩阵变换(图形变形的机制) 图形组合 给图形绘制阴影 绘制 ...
- 仿Material UI框架的动画特效
Material UI是一款功能非常强大,界面却十分清新简洁的CSS框架,Material UI利用了Google的Material Design 全新设计语言,并且让每一个UI组件都变得非常独立,因 ...
- ajax温习
工作中一直有写JS,也一直有用jquery,在感受jquery便利之余,也对它产生了依赖,已至于许多功能只知使用而不知原生写法,就像ajax. 今天不小心翻看了以前学习的视频,温故了一下原生ajax写 ...
- Atitit.html css 浏览器原理理论概论导论attilax总结
Atitit.html css 浏览器原理理论概论导论attilax总结 1.1. 浏览器是怎样工作的:渲染引擎,HTML解析(连载二)1 2. 5.1.1 DOM标准 1011 3. <We ...