Java线程和多线程(二)——对象中的wait,notify以及notifyAll方法
Java对象中的wait,notify以及notifyAll方法
在Java的Object类中包含了3个final的方法,这三个方法允许线程来交流资源是否被锁定。这三个方法就是wait(),notify()以及notifyAll().
在对象上调用这三个方法的线程需要包含一个对象监视器(锁),否则就会抛出java.lang.IllegalMonitorStateException异常。
wait方法
对象的wait方法有三个,一个是令对象等待任何线程来调用notify或者notifyAll方法来令该对象在当前线程唤醒。另外两个将当前线程置于等待状态,等到特定的时间来唤醒。
wait()wait(long millis)wait(long millis, int nanos)
notify方法
notify方法仅仅唤醒一个线程,令线程开始执行。所以,如果有多个线程等待一个对象的时候,这个方法只能唤醒一个线程。而唤醒的线程的选择是依赖于操作系统对于线程的管理的。
notifyAll方法
notifyAll方法会唤醒所有等待改对象的线程,尽管哪一个线程会优先执行时取决于操作系统的线程调度的。
以上的三个方法都可以用来实现生产者消费者问题。
其中,消费者线程会等待队列中的对象而生产者将对象放入队列并唤醒所有等待的线程。
下面的例子将解释多线程如何在同一个对象上使用wait,notify以及notifyAll方法。
Message类
参考代码,Message类就是我们操作的wait,notify以及notifyAll方法的对象:
package com.sapphire.concurrency;
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.sapphire.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());
}
}
}
Notifier类
Notifier类是处理Message对象,然后调用notify方法来唤醒等待Message对象的线程的:
package com.sapphire.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();
}
}
}
测试代码
package com.sapphire.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");
}
}
当我们执行上面的程序时,我们会看到如下的输出,但是程序不会结束,因为有两个线程在等待Message对象,而我们调用的notify方法仅仅唤醒了其中的一个线程,另一个线程仍然处于等待状态,等待被唤醒。
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
如果我们调整前面的代码,在Notifier类中调用notifyAll而不是调用notify方法的话,将会有如下输出:
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线程,所以程序完成了全部执行。
Java线程和多线程(二)——对象中的wait,notify以及notifyAll方法的更多相关文章
- 【Java并发系列02】Object的wait()、notify()、notifyAll()方法使用
一.前言 对于并发编程而言,除了Thread以外,对Object对象的wati和notify对象也应该深入了解其用法,虽然知识点不多. 二.线程安全基本知识 首先应该记住以下基本点,先背下来也无妨: ...
- Java Object对象中的wait,notify,notifyAll的理解
wait,notify,notifyAll 是定义在Object类的实例方法,用于控制线程状态,在线程协作时,大家都会用到notify()或者notifyAll()方法,其中wait与notify是j ...
- Java 线程池(二)
简介 在上篇 Java 线程池(一) 我们介绍了线程池中一些的重要参数和具体含义,这篇我们看一看在 Java 中是如何去实现线程池的,要想用好线程池,只知其然是远远不够的,我们需要深入实现源码去了解线 ...
- java工具类之按对象中某属性排序
import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang ...
- Java 多线程学习笔记:wait、notify、notifyAll的阻塞和恢复
前言:昨天尝试用Java自行实现生产者消费者问题(Producer-Consumer Problem),在coding时,使用到了Condition的await和signalAll方法,然后顺便想起了 ...
- 多线程协作wait、notify、notifyAll方法简介理解使用 多线程中篇(十四)
在锁与监视器中有对wait和notify以及notifyAll进行了简单介绍 所有对象都有一个与之关联的锁与监视器 wait和notify以及notifyAll之所以是Object的方法就是因为任何一 ...
- 关于java的wait、notify、notifyAll方法
wait.notify.notifyAll 遇到的问题 之前开发打印机项目,因为需要使用多线程技术,当时并不怎么理解,一开始随意在方法体内使用wait.notify.notifyAll 方法导致出现了 ...
- keepalived中vrrp_script,track_script,notify的使用方法
keepalived中vrrp_script,track_script,notify的使用方法转自:https://blog.51cto.com/liuzhengwei521/1929589 可以在k ...
- Java线程和多线程(十二)——线程池基础
Java 线程池管理多个工作线程,其中包含了一个队列,包含着所有等待被执行的任务.开发者可以通过使用ThreadPoolExecutor来在Java中创建线程池. 线程池是Java中多线程的一个重要概 ...
随机推荐
- zabbix自定义item(v3.4)
1 添加user key agent.conf UnsafeUserParameters=1 UserParameter=mysql_if_running,sh /app/zabbix/alertsc ...
- 优先队列 HDOJ 5437 Alisha's Party
题目传送门 题意:一人过生日,很多人排着队送礼物.排队顺序是礼物价值大的优先,如果相等先来的优先.有m次开门,当t个人到了会开门让p个人进门.最后一次让门外的所有人按顺序进门.有q次询问,问第x个进门 ...
- System.Web.Mvc 和 using System.Net.Http 的 Filter
在尝试给webapi增加 ExceptionFilter时,出现了错误,经查询区别如下: System.Web.Mvc.Filters 是给mvc用的 System.Web.Http.Filters ...
- Include,Forward,sendRedirct的区别(转)
三者在servlet中的最大区别是: Include和Forward:将当前请求转到另外一个JSP或者servlet处理. sendRedirct:将当前请求返回到浏览器,带上要redirect的UR ...
- iOS7改变状态栏文字颜色
1在Info.plist中设置UIViewControllerBasedStatusBarAppearance 为NO2 在需要改变状态栏颜色的 AppDelegate中在 didFinishLaun ...
- MongoDB管理练习
一.索引 1.插入10W条数据 文档内容为:{name:zs-i,age:1} 2016-06-07T14:35:57.041+0800 I CONTROL [initandlisten] > ...
- jsonp对付同源策略
当 协议不同或者域名/ip不同或者端口号不同 , 都不算是同源 这时候 源生的ajax 就不能进行数据请求了 JSONP json with padding 在平时的开发中也发现了 ,当我们请求 ...
- Javascript异步编程的常用方法
Javascript语言的执行环境是"单线程"(single thread).所谓"单线程",就是指一次只能完成一件任务.如果有多个任务,就必须排队,前面一个任 ...
- help命令
help——获得Shell内置命令的帮助信息 命令所在路径:Shell内置命令 示例1: # help cd 使用which或者whereis查找不到路径的命令一般是Shell内置命令,cd就是一个S ...
- MFC隐藏在黑暗之中的大坑
大坑一:CDC会随着窗口状态的改变而改变 void K5::OnPaint() { CDC *pDC=this->GetDC(); //CDC最好设为局部变量 ... this->Rele ...