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 ...
随机推荐
- 冲刺阶段 day 6
项目进展:学生管理这部分已经进展的差不多了,调试了几遍,改了几个小Bug之后就没有什么问题了,基本完成,如若后续还有一些新的功能到时候再自行加入.明天开始教师部分. 存在问题:我觉得我们的项目还是比较 ...
- [ACM_暴力][ACM_几何] ZOJ 1426 Counting Rectangles (水平竖直线段组成的矩形个数,暴力)
Description We are given a figure consisting of only horizontal and vertical line segments. Our goal ...
- JQuery ajax url传值与data传值的区别
url传中文,乱码,即便charset为 UTF-8, $.ajax({ type: "POST", cache: false, url: "/Prod ...
- 解析json实例
解析项目目录中的一个json文件,将之转化为List的一个方法. package com.miracles.p3.os.util; import com.miracles.p3.os.mode.Vid ...
- Java程序员的日常 —— static的用法讲解实践
之前文章说过Java中static的作用,有朋友想看个例子.于是便抽空写了个小栗子 代码 package xing.test.thinking.chap5; class A{ public A() { ...
- atitit. orm mapping cfg 映射配置(3)-------hbnt one2maney cfg
atitit. orm mapping cfg 映射配置(3)-------hbnt one2maney cfg 1. 建立list 1 2. 配置xml 1 3. Hibernate中Set和L ...
- php中的邮件技术
前言:程序员不谈恋爱就是对物质世界太贪恋 一.通过smtp服务来发送邮件 使用php中的mail()实现邮件的发送; bool mail ( string $to , string $subject ...
- windows必备,命令行工具cmder
下载cmder并安装! 64位可下,亲测: http://www.wmzhe.com/soft-31133.html 创建文件夹并进入文件夹命令: mkdir web-server && ...
- win10蓝屏问题,关于驱动kisSaasUrlRedirectKnl64.sys 的
上周末刚从win7升级到win10:今天出现了两次蓝屏了,都是显示: xxxxxxx 百度知道链接---http://zhidao.baidu.com/question/164141456570387 ...
- ZooKeeper典型应用场景一览
原文地址:http://jm-blog.aliapp.com/?p=1232 ZooKeeper典型应用场景一览 数据发布与订阅(配置中心) 发布与订阅模型,即所谓的配置中心,顾名思义就是发布者将数据 ...