前言:昨天尝试用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的阻塞和恢复的更多相关文章

  1. Java 多线程学习笔记:wait、notify、notifyAll的阻塞和恢复

    前言:昨天尝试用Java自行实现生产者消费者问题(Producer-Consumer Problem),在coding时,使用到了Condition的await和signalAll方法,然后顺便想起了 ...

  2. java 多线程之wait(),notify,notifyAll(),yield()

    wait(),notify(),notifyAll()不属于Thread类,而是属于Object基础类,也就是说每个对像都有wait(),notify(),notifyAll()的功能.因为都个对像都 ...

  3. Java多线程8:wait()和notify()/notifyAll()

    轮询 线程本身是操作系统中独立的个体,但是线程与线程之间不是独立的个体,因为它们彼此之间要相互通信和协作. 想像一个场景,A线程做int型变量i的累加操作,B线程等待i到了10000就打印出i,怎么处 ...

  4. Java多线程学习之wait、notify/notifyAll 详解

    1.wait().notify/notifyAll() 方法是Object的本地final方法,无法被重写. 2.wait()使当前线程阻塞,前提是 必须先获得锁,一般配合synchronized 关 ...

  5. 【java线程系列】java线程系列之线程间的交互wait()/notify()/notifyAll()及生产者与消费者模型

    关于线程,博主写过java线程详解基本上把java线程的基础知识都讲解到位了,但是那还远远不够,多线程的存在就是为了让多个线程去协作来完成某一具体任务,比如生产者与消费者模型,因此了解线程间的协作是非 ...

  6. Object的wait/notify/notifyAll&&Thread的sleep/yield/join/holdsLock

    一.wait/notify/notifyAll都是Object类的实例方法 1.wait方法:阻塞当前线程等待notify/notifyAll方法的唤醒,或等待超时后自动唤醒. wait等待其实是对象 ...

  7. 使用ReentrantLock和Condition来代替内置锁和wait(),notify(),notifyAll()

    使用ReentrantLock可以替代内置锁,当使用内置锁的时候,我们可以使用wait() nitify()和notifyAll()来控制线程之间的协作,那么,当我们使用ReentrantLock的时 ...

  8. java多线程14 :wait()和notify()/notifyAll()

    轮询 线程本身是操作系统中独立的个体,但是线程与线程之间不是独立的个体,因为它们彼此之间要相互通信和协作. 想像一个场景,A线程做int型变量i的累加操作,B线程等待i到了10000就打印出i,怎么处 ...

  9. Java 多线程 线程的五种状态,线程 Sleep, Wait, notify, notifyAll

    一.先来看看Thread类里面都有哪几种状态,在Thread.class中可以找到这个枚举,它定义了线程的相关状态: public enum State { NEW, RUNNABLE, BLOCKE ...

随机推荐

  1. Asp.Net Web API 2第七课——Web API异常处理

    前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html 本文主要来讲解Asp.Ne ...

  2. Microsoft Azure开发体验 – 网络报名系统

    去年底RP好抢到了中国版Azure的使用机会,最近社团里讨论到9月份招新的问题,就用Azure Website和Azure Table Storage打造了这个报名系统. 网站放在 http://jo ...

  3. SharePoint 基于 REST API使用简介

    之前已经介绍了SP2010中支持CSOM的API进行远程访问SharePoint,但是CSOM的API仍然有一定的局限性,首先使用CSOM类库是基于.Net的,因此也将使用CSOM限制在了.Net平台 ...

  4. mysql 密码重置

    1.停止mysql服务(以管理员身份,在cmd命令行下运行) net stop mysql 2.使用命令启动mysql数据库,跳过权限验证 mysqld -nt --skip-grant-tables ...

  5. Asset Catalog Help (二)---Creating an Asset Catalog

    Creating an Asset Catalog Create an asset catalog to simplify management of your app’s images. 创建一个a ...

  6. ucos操作系统的内核有哪些调度方法

    1)时间片轮番调度法 假设系统中有5个任务,T1,T2,T3,T4,T5,这个时候,操作系统为每一个任务分配时间,比如说我们为T1任务分配10毫秒,为T2任务分配20毫秒,为T3任务分配5毫秒,为T4 ...

  7. python先序、中序、后序排序

    #encoding=utf-8 class Tree(): def __init__(self,leftjd=0,rightjd=0,data=0): self.leftjd = leftjd sel ...

  8. iPhone屏幕尺寸、分辨率及适配

    转:http://blog.csdn.net/phunxm/article/details/42174937 目录(?)[+]   1.iPhone尺寸规格 设备 iPhone 宽 Width 高 H ...

  9. 关于mysql备份说明

    #mysqlpump压缩备份vs数据库 三个并发线程备份,消耗时间:222smysqlpump -uzjy -p -h192.168.123.70 --single-transaction --def ...

  10. jxl 2.6.12 与 jxl 2.3.0 稳定版性能比较

    jxl 2.3.0 org.jxls:jxls:2.3.0 org.jxls:jxls-poi:1.0.9 org.jxls:jxls-jexcel:1.0.6 jxls-reader:2.0.2 j ...