[译]Java Thread wait, notify和notifyAll示例
Java Thread wait, notify和notifyAll示例
Java上的Object类定义了三个final方法用于不同线程间关于某资源上的锁状态交互,这三个方法是:wait(), notify()和notifyAll()。
当前线程可以在任意对象上调用上述的方法,前提是当前线程是此对象的监视器(object monitors)的持有者;如果未持有该monitor而调用上述方法时会抛出java.lang.IllegalMonitorStateException。
Wait
Object上有三种重载的wait方法,其中之一是调用了object.wait()方法的线程会无限等待下去,直到有其他线程调用了相同对象上的notify或notifyAll方法用于唤醒其他线程;另外两个方法可以指定线程被唤醒之前的等待时间。
notify
notify方法用于唤醒调用了object.wait()方法的等待线程,但每次调用只能唤醒一次。被唤醒的线程会变为Runnable,进而被调度执行。如果在某个object上有多个线程在等待,一次notify调用只能唤醒其中一个。具体哪个线程被唤醒取决于操作系统的线程管理的具体实现。
notifyAll
notifyAll可以唤醒在相同对象上调用了wait()方法的所有线程,但哪个线程先开始执行也依赖于操作系统的实现。
上面的方法可用于解决生产者-消费者问题,在生产者-消费者场景中,消费者线程等待从队列中消费对象,而生产者会把对象放到队列中,并通知等待线程有对象可消费。
下面看一个在相同对象上使用了wait,notify,notifyAll方法的多线程的例子。
Message
定义一个普通的Java bean:Message,下面的线程将会在Message对象上调用wait和notify方法。
public class Message {
private String msg;
public Message(String str){
this.msg=str;
}
public String getMsg() {
return msg;
}
public void setMsg(String str) {
this.msg=str;
}
}
Waiter
Waiter是一个等待线程,等待其他线程调用notify来唤醒自己并继续未完成的任务。
package com.journaldev.concurrency;
public class Waiter implements Runnable{
private Message msg;
public Waiter(Message m){
this.msg=m;
}
@Override
public void run() {
String name = Thread.currentThread().getName();
synchronized (msg) {
try{
System.out.println(name+" waiting to get notified at time:"+System.currentTimeMillis());
msg.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(name+" waiter thread got notified at time:"+System.currentTimeMillis());
//process the message now
System.out.println(name+" processed: "+msg.getMsg());
}
}
}
或许你已经在代码中注意到,Waiter线程通过synchronized(同步代码块)获得了Message对象上的监视器。
Notifier
Notifier线程处理Message对象,并调用该对象上的notify方法,用于唤醒其他等待Message对象的线程。
package com.journaldev.concurrency;
public class Notifier implements Runnable {
private Message msg;
public Notifier(Message msg) {
this.msg = msg;
}
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println(name+" started");
try {
Thread.sleep(1000);
synchronized (msg) {
msg.setMsg(name+" Notifier work done");
msg.notify();
// msg.notifyAll();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
同样,在Notifier线程中也通过synchronized来获取Message对象上的监视器。
WaitNotifyTest
下面的测试代码创建了多个Waiter和Notifier线程。
package com.journaldev.concurrency;
public class WaitNotifyTest {
public static void main(String[] args) {
Message msg = new Message("process it");
Waiter waiter = new Waiter(msg);
new Thread(waiter,"waiter").start();
Waiter waiter1 = new Waiter(msg);
new Thread(waiter1, "waiter1").start();
Notifier notifier = new Notifier(msg);
new Thread(notifier, "notifier").start();
System.out.println("All the threads are started");
}
}
调用上面的程序,将会看到如下的输出:
waiter waiting to get notified at time:1356318734009
waiter1 waiting to get notified at time:1356318734010
All the threads are started
notifier started
waiter waiter thread got notified at time:1356318735011
waiter processed: notifier Notifier work done
- notify()
但是别激动,程序并未结束,因为上面的代码中有两个waiter线程都在等待同一个Message对象,但只有一次notify()方法调用,所以只有一个线程被唤醒,而另一个线程只能继续等待。 - notifyAll() 如果把Notifier中的notify()注释掉,并把notifyAll()的注释打开,再次调用上面的测试程序,将会有不同的输出:
waiter waiting to get notified at time:1356318917118
waiter1 waiting to get notified at time:1356318917118
All the threads are started
notifier started
waiter1 waiter thread got notified at time:1356318918120
waiter1 processed: notifier Notifier work done
waiter waiter thread got notified at time:1356318918120
waiter processed: notifier Notifier work done
因为notifyAll()方法会把两个waiter线程都唤醒,并先后执行,程序结束。
原文链接:http://www.journaldev.com/1037/java-thread-wait-notify-and-notifyall-example
[译]Java Thread wait, notify和notifyAll示例的更多相关文章
- Java Thread wait, notify and notifyAll Example
Java Thread wait, notify and notifyAll Example Java线程中的使用的wait,notify和nitifyAll方法示例. The Object clas ...
- [译]Java Thread Sleep示例
Java Thread Sleep示例 java.lang.Thread sleep(long millis)方法被用来暂停当前线程的执行,暂停时间由方法参数指定,单位为毫秒.注意参数不能为负数,否则 ...
- [译]Java Thread join示例与详解
Java Thread join示例与详解 Java Thread join方法用来暂停当前线程直到join操作上的线程结束.java中有三个重载的join方法: public final void ...
- java wait()和notify()、notifyAll()
图见<JAVA并发编程的艺术>P98-101 这三个方法都是java.lang.Object的方法,用于协调多个线程对共享数据的存取,必须在synchronized语句块中使用!这三个方法 ...
- Java的wait(), notify()和notifyAll()使用小结
wait(),notify()和notifyAll()都是java.lang.Object的方法: wait(): Causes the current thread to wait until an ...
- Java多线程 wait, notify 和 notifyAll
Java的Object类 public class Object { public final native void notify(); public final native void notif ...
- Java的wait(), notify()和notifyAll()使用心得(转)
本篇文章是对java的 wait(),notify(),notifyAll()进行了详细的分析介绍,需要的朋友参考下wait(),notify()和notifyAll()都是java.lang.Obj ...
- java中的notify和notifyAll有什么区别?
先说两个概念:锁池和等待池 锁池:假设线程A已经拥有了某个对象(注意:不是类)的锁,而其它的线程想要调用这个对象的某个synchronized方法(或者synchronized块),由于这些线程在进入 ...
- 精通java并发-wait,notify和notifyAll的总结(含案例)
目前CSDN,博客园,简书同步发表中,更多精彩欢迎访问我的gitee pages wait,notify和notifyAll 总结 在调用wait方法时,线程必须要持有被调用对象的锁,当调用wait方 ...
随机推荐
- 20种常用的DOS命令小结
先介绍一下通配符的概念. 通配符*和? *表示一个字符串 ?只代表一个字符 注意通配符只能通配文件名或扩展名,不能全都表示.例如我们要查找以字母y开头的所有文件,可以输入以下命令:dir y*.*:如 ...
- 关于Android M RuntimePermission的问题
关于shouldShowRequestPermissionRationale的理解, 在onRequestPermissionsResult里如果用户拒绝了权限, 可以调用这个api, 返回true, ...
- Python实践之(七)逻辑回归(Logistic Regression)
机器学习算法与Python实践之(七)逻辑回归(Logistic Regression) zouxy09@qq.com http://blog.csdn.net/zouxy09 机器学习算法与Pyth ...
- C++的64位整数
在做ACM题时,经常都会遇到一些比较大的整数.而常用的内置整数类型常常显得太小了:其中long 和 int 范围是[-2^31,2^31),即-2147483648~2147483647.而unsig ...
- bash的for循环从命令读取值
bash的for循环可以很方便地从命令读取值,还可以指定分割值 下面的程序可以打印文件的内容,前面加上行号 #!/bin/bash # 打印每一行的内容,前面加行号 filename="/h ...
- Linux内核--网络栈实现分析(一)--网络栈初始化--转
转载地址 http://blog.csdn.net/yming0221/article/details/7488828 作者:闫明 本文分析基于内核Linux Kernel 1.2.13 以后的系列博 ...
- 小白日记38:kali渗透测试之Web渗透-手动漏洞挖掘(四)-文件上传漏洞
手动漏洞挖掘 文件上传漏洞[经典漏洞,本身为一个功能,根源:对上传文件的过滤机制不严谨] <?php echo shell_exec($_GET['cmd']);?> 直接上传webshe ...
- TCP/IP协议原理与应用笔记19:IP分组的交付和路由选择
1. 引言: (1)互联网结构: 信息:IP分组(直接广播地址(Directed Broadcast Address),其指定了在一个特定网络中的"所有主机".) 节点:路由器.主 ...
- myEclipse6.5与数据库(SQL Server2008)连接遇到的问题(自己总结的干货)<用SSH框架的时候,用servlet+javabean+jsp的时候>
昨天因为学习SSH框架的搭建,时隔一年又重新遇到了myEclipse连接数据库的问题.废话不多说,上干货 (以下全部按照我遇到的问题的顺序,也就是没有顺序,就是任性) 请注意:这是在myEclipse ...
- SSIS 学习(7):包配置(下)【转】
经过前面几个章节的学习,我们开发的ETL包算已经完成一大半了,但是还不够完美,正如一场足球比赛,前面大家打得很辛苦,传接得也很漂亮,但 是临门一脚的技术不过关,进不了球,一切都是白搭.今天我们就来为大 ...