Java多线程--wait(),notify(),notifyAll()的用法
忙等待没有对运行等待线程的 CPU 进行有效的利用(而且忙等待消耗cpu过于恐怖,请慎用),除非平均等待时间非常短。否则,让等待线程进入睡眠或者非运行状态更为明智,直到它接收到它等待的信号。
Java 有一个内建的等待机制来允许线程在等待信号的时候变为非运行状态。java.lang.Object 类定义了三个方法,wait()、notify()和 notifyAll()来实现这个等待机制。
但在使用wait()、notify()和 notifyAll()必须获取该对象的锁,否则的话会抛异常IllegalMonitorStateException!
wait():沉睡当前线程。
notify():随机唤醒一个正在等待当前对象的线程,不可以指定唤醒哪一个。
notify():唤醒所有正在等待当前对象的线程。
注意(同步块):
1.当一个线程被唤醒以后,并不会立即退出wait()方法去执行接下来的代码,直到调用notify()方法的线程退出它自己的同步块以后。
2.同样的使用notifyAll()方法以后,并不是所有的线程都会立即退出wait()方法,获得该对象锁的线程一个接一个的退出。
import org.junit.Test; import static java.lang.Thread.sleep; public class MyWaitNotify { public class Monitor{ } Monitor monitorObject = new Monitor();
boolean waitSign = false; public void doWait(){
synchronized (monitorObject){
while (!waitSign)
{
try {
monitorObject.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} public void doNotify(){
synchronized (monitorObject){
waitSign=true;
monitorObject.notify();
}
} public void doNotifyAll(){
synchronized (monitorObject){
waitSign=true;
monitorObject.notifyAll();
}
} @Test
public void testNotify(){ new Thread(){
public void run(){
try {
System.out.println("线程1:启动");
sleep(5000);
System.out.println("线程1:notify;");
doNotify();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程结束");
}
}.start(); System.out.println("主线程wait");
doWait();
System.out.println("主线程被激活");
} @Test
public void testNotifyAll() { new Thread(){
public void run(){
try {
System.out.println("线程1:启动");
sleep(5000);
System.out.println("线程1:notifyAll;");
doNotifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程1:结束");
}
}.start(); new Thread(){
public void run(){
System.out.println("线程2:等待");
doWait();
try {
sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程2:激活");
System.out.println("线程2:结束");
}
}.start(); System.out.println("主线程wait");
doWait();
System.out.println("主线程:激活");
try {
sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("主线程:完成");
} }
MyWaitNotify类中:
1.testNotify()方法中,测试了主线程wait,子线程notify。
2.testNotifyAll()方法中,测试了主线程wait,子线程2wait,子线程1notifyAll。
注意容易发生的问题:
1.notify()方法执行在wait()方法之前,那么会造成调用wait()方法的线程永远在等待,不在醒来。
解决方法:将notify()信号通过变量存储,任何一个线程需要wait()之前必须要检测该变量,保证没有notify才能wait。
2.调用wait()等待的线程可能会出现“假唤醒”的情况,也就是在没有notify()的情况下,调用wait()的线程自动醒来。
解决方法:通过while循环检测notify()信号变量,如果notify()信号变量表示没有线程执行过notify()那说明确实是“假唤醒”,则需要继续wait()。
public void doWait(){
synchronized (monitorObject){
while (!waitSign)
{
try {
monitorObject.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
参考文档:http://wiki.jikexueyuan.com/project/java-concurrent/thread-communication.html
Java多线程--wait(),notify(),notifyAll()的用法的更多相关文章
- Java多线程_wait/notify/notifyAll方法
关于这三个方法,我们可以查询API得到下列解释: wait():导致当前的线程等待,直到其他线程调用此对象的notify( ) 方法或 notifyAll( ) 方法或者指定的事件用完 notify( ...
- java 为什么wait(),notify(),notifyAll()必须在同步方法/代码块中调用?
在Java中,所有对象都能够被作为"监视器monitor"——指一个拥有一个独占锁,一个入口队列和一个等待队列的实体entity.所有对象的非同步方法都能够在任意时刻被任意线程调用 ...
- 线程中wait/notify/notifyAll的用法
前言 多线程时,最关注的就是线程同步,线程间的同步一般用锁来实现,常见的锁就是synchronized和lock.用了synchronized,就不得不提到wait/notify/notifyAll. ...
- 多线程-wait/notify/notifyAll
引言 在Java中,可以通过配合调用Object对象的wait,notify和notifyAll来实现线程间的通信. 在线程中调用wait方法,将阻塞带带其他线程的通知(其他线程调用notify或no ...
- 玩转java多线程(wait和notifyAll的正确使用姿势)
转载请标明博客的地址 本人博客和github账号,如果对你有帮助请在本人github项目AioSocket上点个star,激励作者对社区贡献 个人博客:https://www.cnblogs.com/ ...
- [转]java 为什么wait(),notify(),notifyAll()必须在同步方法/代码块中调用?
在 Java中,所有对象都能够被作为"监视器monitor"——指一个拥有一个独占锁,一个入口队列和一个等待队列的实体entity. 所有对象的非同步 方法都能够在任意时刻被任意线 ...
- java多线程wait notify join
wait notify 几个注意点: wait 与 notify/notifyAll 方法必须在同步代码块中使用,即要先对调用对象加锁. 当线程执行wait()时,会把当前的锁释放,然后让出CPU,进 ...
- java使用wait(),notify(),notifyAll()实现等待/通知机制
public class WaitNotify { static boolean flag=true; static Object lock=new Object(); static class Wa ...
- java 为什么wait(),notify(),notifyAll()必须在同步(Synchronized)方法/代码块中调用?
wait()作用:该方法用来将当前线程置入休眠状态,直到接到通知或被中断为止.条件:在调用wait()之前,线程必须要获得该对象的对象级别锁,即只能在同步方法或同步块中调用wait()方法.进入wai ...
随机推荐
- 【汇总】iOS开发及Xcode使用中遇到的一些报错问题汇总
这里整合下在开发过程中遇到过的一些报错问题和解决办法:(今天开始逐渐增加) Xcode编译错误集锦:http://www.cnblogs.com/ios-wmm/p/3402261.html ...
- cocos2dx 2.x 骨骼动画优化
本文原链接:http://www.cnblogs.com/zouzf/p/4450861.html 公司用的骨骼动画的版本貌似还停留在2.1之前的年代而已没有更新,该因各种历史原因吧,而有个大项目“一 ...
- Android-NDK编译:cocos2d-x(二)
看了看NDK的文档....里面总是莫名的会提下windows需要cygwin环境... 但是cocos2d-x3.0alpha1 中, 编译samples的python脚本 cocos2d-x3/bu ...
- iOS开发之应用内检测手机锁屏,解锁状态
iPhone的锁屏监测分为两种方式监听: 1. 程序在前台,这种比较简单.直接使用Darwin层的通知就可以了: #import <notify.h> #define Notificati ...
- 墓地雕塑-LA3708
https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=20& ...
- CLR via C#深解笔记六 - 泛型
面向对象编程一个好处就是“代码重用”,极大提高了开发效率.如是,可以派生出一个类,让它继承基类的所有能力,派生类只需要重写虚方法,或添加一些新的方法,就可以定制派生类的行为,使之满足开发人员的需求. ...
- unity4.6 failed to update unity web player
unity4.6 failed to update unity web player 新升级的 4.6.2P2 版本修复了IOS很多的bug. 但突然发现导出的Web版本反而不能工作了. “faile ...
- yousa_team团队项目 兼职平台 完成展示
我们团队的团队项目是一个大学生兼职网站,商家可以在网站上发布信息,学生对相应的岗位进行预约,然后根据信誉度来表示用户的信誉,整个平台由管理员监控, 包括修改错误信息,修改用户信誉度,删除过期信息,接受 ...
- [前端]npm安装慢,换用淘宝的镜像
镜像使用方法(三种办法任意一种都能解决问题,建议使用第三种,将配置写死,下次用的时候配置还在): 通过config命令 npm config set registry https://registry ...
- Vim杂记:markdown插件
一.安装插件 从以下地址下载压缩包 github下载:https://github.com/plasticboy/vim-markdown plasticboy下载:http://plasticboy ...