1.阻塞阶段
线程调用wait()方法进入阻塞阶段,前提是获得monitor锁才可以(object的wait(),notify(),notifyAll()都需要先获得锁,不然会抛出异常)。
2.直到以下四种情况发生才会被唤醒
(1)另一个线程调用这个对象的notify()方法且刚好唤醒的是本线程,这个方法只会选取一个线程唤醒。

package threadcoreknowledge.threadobjectclasscommonmethods;/*** @Author: panda* 展示wait和notify的基本用法* 1.研究代码的执行顺序* 2.证明wait释放锁**/
public class Wait {public static Object object = new Object();static class Thread1 extends Thread{@Overridepublic void run(){synchronized (object){System.out.println(Thread.currentThread().getName()+"开始执行了");try {//这里会释放这把锁,如果不释放这把锁,Thread2是没有办法执行的object.wait();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("线程"+Thread.currentThread().getName()+"获取到了锁");}}}static class Thread2 extends Thread{@Overridepublic void run() {synchronized (object){object.notify();System.out.println("线程"+Thread.currentThread().getName()+"调用了notify()");//即使调用了notify()唤醒了Thread1,但是依旧没有释放这把锁,等到代码执行完成才会释放锁,释放锁后Thread1才有机会获得这把锁继续执行。}}}public static void main(String[] args) throws InterruptedException {Thread1 thread1 = new Thread1();Thread2 thread2 = new Thread2();thread1.start();//这里保证执行顺序Thread.sleep(200);thread2.start();}
}
输出
Thread-0开始执行了
线程Thread-1调用了notify()
线程Thread-0获取到了锁

(2)另一个线程调用这个对象的notifyAll()方法,会唤醒全部wait状态下的线程。

package threadcoreknowledge.threadobjectclasscommonmethods;/*** @Author: panda* 三个线程,线程1和线程2首先被阻塞,线程3唤醒它们。notify,notifyAll* start先执行,不代表线程先启动**/
public class WaitNotifyAll implements Runnable{private static final Object resourceA = new Object();@Overridepublic void run() {synchronized (resourceA){System.out.println(Thread.currentThread().getName()+" got resourceAlock");try {System.out.println(Thread.currentThread().getName()+" waits to start.");resourceA.wait();System.out.println(Thread.currentThread().getName()+" s waiting to end");} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) throws InterruptedException {Runnable r = new WaitNotifyAll();Thread threadA = new Thread(r);Thread threadB = new Thread(r);Thread threadC = new Thread(new Runnable() {@Overridepublic void run() {synchronized (resourceA){resourceA.notifyAll();System.out.println(Thread.currentThread().getName()+" notified");}}});threadA.start();threadB.start();Thread.sleep(200);threadC.start();}
}
输出
Thread-0 got resourceAlock
Thread-0 waits to start.
Thread-1 got resourceAlock
Thread-1 waits to start.
Thread-2 notified
Thread-1 s waiting to end
Thread-0 s waiting to end

如果将notifyAll()替换成notify(),只会唤醒其中一个wait状态下的线程

package threadcoreknowledge.threadobjectclasscommonmethods;/*** @Author: panda* 三个线程,线程1和线程2首先被阻塞,线程3唤醒它们。notify,notifyAll* start先执行,不代表线程先启动**/
public class WaitNotifyAll implements Runnable{private static final Object resourceA = new Object();@Overridepublic void run() {synchronized (resourceA){System.out.println(Thread.currentThread().getName()+" got resourceAlock");try {System.out.println(Thread.currentThread().getName()+" waits to start.");resourceA.wait();System.out.println(Thread.currentThread().getName()+" s waiting to end");} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) throws InterruptedException {Runnable r = new WaitNotifyAll();Thread threadA = new Thread(r);Thread threadB = new Thread(r);Thread threadC = new Thread(new Runnable() {@Overridepublic void run() {synchronized (resourceA){resourceA.notify();System.out.println(Thread.currentThread().getName()+" notified");}}});threadA.start();threadB.start();Thread.sleep(200);threadC.start();}
}
输出
Thread-0 got resourceAlock
Thread-0 waits to start.
Thread-1 got resourceAlock
Thread-1 waits to start.
Thread-2 notified
Thread-0 s waiting to end

(3)过了wait(long timeout)规定的超时时间,如果传入0就是永久等待。
(4)线程自身调用了interrupt()方法
3.遇到中断
假设线程已经执行了wait()方法,如果在此期间被中断了,它会和sleep()一样抛出 InterruptedException并且释放掉当前已经获得的monitor。
4.测试当线程进入waiting状态,线程遇到中断时是否能立即获得monitor锁响应中断

package threadcoreknowledge.threadobjectclasscommonmethods;import java.util.concurrent.TimeUnit;/*** @Author: panda* @Description: 测试当线程进入waiting状态,线程遇到中断时是否能立即获得monitor锁响应中断*  结论:还是要等其他线程释放monitor锁后才能获得* @Date: 2019/10/11 10:31**/
public class WaitInterrupted {private static final Object lock = new Object();private class Wait implements Runnable{@Overridepublic void run() {threadWait();}}private class Count implements Runnable{@Overridepublic void run() {count();}}private  void count(){synchronized(lock){System.out.println(Thread.currentThread().getName()+"拿到了monitor锁");for (int i = 1 ; i <= 100000 ; i++){System.out.println(Thread.currentThread().getName() + " : " + i);}System.out.println(Thread.currentThread().getName()+"释放了monitor锁");}}private void  threadWait(){synchronized (lock){System.out.println(Thread.currentThread().getName()+"拿到了monitor锁");try {lock.wait();} catch (InterruptedException e) {System.out.println(Thread.currentThread().getName()+ "遇到中断线程状态从WAITING状态被唤醒成:"+ Thread.currentThread().getState());e.printStackTrace();}System.out.println("count这时候打印暂停,sleep不会释放当前锁");try {TimeUnit.SECONDS.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"释放了monitor锁");System.out.println("count继续打印剩下的数字");}}public Count getCount(){return new Count();}public Wait getWait(){return new Wait();}public static void main(String[] args)throws InterruptedException {WaitInterrupted waitInterrupted = new WaitInterrupted();Thread wait = new Thread(waitInterrupted.getWait(),"wait");wait.start();//让wait先执行TimeUnit.SECONDS.sleep(1);Thread count = new Thread(waitInterrupted.getCount(),"count");count.start();//让count线程先打印些数字出来再进行中断TimeUnit.SECONDS.sleep(1);wait.interrupt();}
}
输出
...
count : 100000
count释放了monitor锁
wait遇到中断线程状态从WAITING状态被唤醒成:RUNNABLE
java.lang.InterruptedExceptionat java.lang.Object.wait(Native Method)at java.lang.Object.wait(Object.java:502)at threadcoreknowledge.threadobjectclasscommonmethods.WaitInterrupted.threadWait(WaitInterrupted.java:41)at threadcoreknowledge.threadobjectclasscommonmethods.WaitInterrupted.access$000(WaitInterrupted.java:11)at threadcoreknowledge.threadobjectclasscommonmethods.WaitInterrupted$Wait.run(WaitInterrupted.java:16)at java.lang.Thread.run(Thread.java:745)
count这时候打印暂停,sleep不会释放当前锁
wait释放了monitor锁
count继续打印剩下的数字

结论:根据输出可以看出,当产生一个中断后wait线程并没有立马获得锁,而只是被唤醒成RUNNABLE状态,等待锁被count线程释放,然后再次获取锁响应中断。

wait,notify,notifyAll作用、方法相关推荐

  1. java多线程notifyall_Java多线程:线程状态以及wait(), notify(), notifyAll()

    1. wait(), notify(), notifyAll()等方法介绍 在Object.java中,定义了wait(), notify()和notifyAll()等接口.wait()的作用是让当前 ...

  2. 线程方法notify/notifyAll源码分析

    众所周知,使用notify/notifyAll方法能唤醒wait等待的线程,那么在底层源码究竟做了些什么呢? 本章内容要解决的问题 问题1:notify/nofityAll真的唤醒了线程吗? 问题2: ...

  3. 线程的状态转换、sleep()、wait()、yeild()、终止线程的方法、线程之间的协作(join()、wait() notify() notifyAll()、await() signal() )

    1.线程的状态转换 1.1 新建(New) 创建后尚未启动 1.2 可运行(Runnable) 可能正在运行,也可能正在等待 CPU 时间片. 包含了操作系统线程状态中的 Running 和 Read ...

  4. 理解notify()/notifyall()/interupt()对于线程里面wait方法的影响

    本文将通过三个程序例子帮助读者理解其中的原理: import java.text.SimpleDateFormat; import java.util.Date; import java.util.c ...

  5. java notify 的作用_java 为什么notify和notifyAll都不起作用?

    叮当猫咪 每个线程初始化的时候都是 c=new C(),锁住的是不同的对象.class Example{    public static void main(String arr[]){      ...

  6. 终于搞懂了sleep/wait/notify/notifyAll

    作者:acupt,专注Java,架构师社区合伙人! sleep/wait/notify/notifyAll分别有什么作用?它们的区别是什么?wait时为什么要放在循环里而不能直接用if? 简介 首先对 ...

  7. [转]java 为什么wait(),notify(),notifyAll()必须在同步方法/代码块中调用?

    在 Java中,所有对象都能够被作为"监视器monitor"--指一个拥有一个独占锁,一个入口队列和一个等待队列的实体entity. 所有对象的非同步 方法都能够在任意时刻被任意线 ...

  8. sleep() wait() notify/notifyAll() 的区别

    看了一下线程这方面的知识,也结合了一些 面试的题 总结如下: 一些基础的就不说了,主要说一下这里面的几个方法,也是object的通用方法. sleep()     wait()     notify/ ...

  9. wait放弃对象锁_终于搞懂了sleep/wait/notify/notifyAll,真的是不容易

    sleep/wait/notify/notifyAll分别有什么作用?它们的区别是什么?wait时为什么要放在循环里而不能直接用if? 简介 首先对几个相关的方法做个简单解释,Object中有几个用于 ...

最新文章

  1. Java SE7新特性之switch语句中使用字符串
  2. 互联网金融下一个风口的或许在新农业领域?
  3. Delphi中点击网页弹出的Alert对话框的确定按钮
  4. vscode 最好的ui主题
  5. php hex2bin nodejs,Nodejs Serialport文档翻译
  6. JQuery 样式设置、追加、移除与切换
  7. 批量提交 kafka_Kafka精华问答|kafka的使用场景是什么?
  8. c语言录像带课程设计,2019信息技术真题共16页word资料
  9. MOSS 2007 Search系列
  10. python程序由三种基本结构组成_python入门基础教程04 Python程序基本组成
  11. Openwrt源码LuCI应用完整说明
  12. 如何将大硬盘对拷到小硬盘
  13. 安徽阜阳计算机高中学校排名,安徽省高中学校实力排名
  14. html微信朋友圈demo,Vue.js实现模拟微信朋友圈开发demo
  15. 几张“有趣”的简图带你理解面试题:String、StringBuffer、StringBuilder区别
  16. 搭建MPI并行计算环境并计算pi值[windows 和 Ubuntu]
  17. Linux系统下 修改服务器用户密码
  18. 《Linux命令行与shell脚本编程大全》第十三章 学习笔记
  19. Vue.js全家桶仿哔哩哔哩动画 (移动端APP)
  20. AIO系列文档(2)----TIO使用

热门文章

  1. 哈尔滨理工大学软件与微电子学院第八届程序设计竞赛同步赛(高年级)
  2. icp备案查询接口查询备案信息
  3. 谷歌浏览器Chrome导入导出文件卡死,崩溃
  4. Java标识符(类名、变量名、方法名、接口名、包名)命名的一般规则
  5. 计算机科学与技术专业,学什么,怎么学,才能找到好工作?
  6. 手眼标定(eye_to_hand)
  7. 教你使用cookie登录
  8. 在 windows 环境下,编写一个批处理程序(算命大师.bat)
  9. 基于安全运营中心的工作总结
  10. 关于定时任务fixedRate和fixedDelay区别最简单的解释