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方法会唤醒所有等待改对象的线程,尽管哪一个线程会优先执行时取决于操作系统的线程调度的。

以上的三个方法都可以用来实现生产者消费者问题

其中,消费者线程会等待队列中的对象而生产者将对象放入队列并唤醒所有等待的线程。

下面的例子将解释多线程如何在同一个对象上使用waitnotify以及notifyAll方法。


Message

参考代码,Message类就是我们操作的waitnotify以及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方法的更多相关文章

  1. 【Java并发系列02】Object的wait()、notify()、notifyAll()方法使用

    一.前言 对于并发编程而言,除了Thread以外,对Object对象的wati和notify对象也应该深入了解其用法,虽然知识点不多. 二.线程安全基本知识 首先应该记住以下基本点,先背下来也无妨: ...

  2. Java Object对象中的wait,notify,notifyAll的理解

    wait,notify,notifyAll 是定义在Object类的实例方法,用于控制线程状态,在线程协作时,大家都会用到notify()或者notifyAll()方法,其中wait与notify是j ...

  3. Java 线程池(二)

    简介 在上篇 Java 线程池(一) 我们介绍了线程池中一些的重要参数和具体含义,这篇我们看一看在 Java 中是如何去实现线程池的,要想用好线程池,只知其然是远远不够的,我们需要深入实现源码去了解线 ...

  4. java工具类之按对象中某属性排序

    import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang ...

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

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

  6. 多线程协作wait、notify、notifyAll方法简介理解使用 多线程中篇(十四)

    在锁与监视器中有对wait和notify以及notifyAll进行了简单介绍 所有对象都有一个与之关联的锁与监视器 wait和notify以及notifyAll之所以是Object的方法就是因为任何一 ...

  7. 关于java的wait、notify、notifyAll方法

    wait.notify.notifyAll 遇到的问题 之前开发打印机项目,因为需要使用多线程技术,当时并不怎么理解,一开始随意在方法体内使用wait.notify.notifyAll 方法导致出现了 ...

  8. keepalived中vrrp_script,track_script,notify的使用方法

    keepalived中vrrp_script,track_script,notify的使用方法转自:https://blog.51cto.com/liuzhengwei521/1929589 可以在k ...

  9. Java线程和多线程(十二)——线程池基础

    Java 线程池管理多个工作线程,其中包含了一个队列,包含着所有等待被执行的任务.开发者可以通过使用ThreadPoolExecutor来在Java中创建线程池. 线程池是Java中多线程的一个重要概 ...

随机推荐

  1. jQuery中的.html()和.text()及.val()区别

    https://www.cnblogs.com/zhang-xun/p/6766264.html

  2. Helvetic Coding Contest 2017 online mirror (teams allowed, unrated) M

    Description The marmots have prepared a very easy problem for this year's HC2 – this one. It involve ...

  3. 自己写的MD5加密原码

    package com.wh.md5; import java.security.MessageDigest; import java.util.Arrays; /** * @author 王恒 * ...

  4. 491 Increasing Subsequences 递增子序列

    给定一个整型数组, 你的任务是找到所有该数组的递增子序列,递增子序列的长度至少是2.示例:输入: [4, 6, 7, 7]输出: [[4, 6], [4, 7], [4, 6, 7], [4, 6, ...

  5. 纯js手动分页

    昨天让做个页面,后台提供所有数据,没有做好分页,需要前端js手动分页. 我参考了 http://www.cnblogs.com/jiechn/p/4095029.html 做了些许改动让分页效果更加完 ...

  6. 26款优秀的Android逆向工程工具

    26款优秀的Android逆向工程工具

  7. React-Native 开发问题整理

    1.内嵌WebView,点击输入框后页面不自动上滚 <activity android:name=".MainActivity" android:label="@s ...

  8. UVA 11971 Polygon 多边形(连续概率)

    题意: 一根长度为n的木条,随机选k个位置将其切成k+1段,问这k+1段能组成k+1条边的多边形的概率? 思路: 数学题.要求的是概率,明显与n无关. 将木条围成一个圆后再开切k+1刀,得到k+1段. ...

  9. 三星系列NXP系列核心板设计研发-迅为嵌入式ARM方案提供商

    多种核心板平台,从硬件原型设计.layout.硬件驱动,操作系统移植.中间到上层应用等方面. 三星系列核心板: 1. SCP-4412核心板 三星Exynos4412 四核 Cortex-A9 主频为 ...

  10. selelinum+PhantomJS 爬取拉钩网职位

    使用selenium+PhantomJS爬取拉钩网职位信息,保存在csv文件至本地磁盘 拉钩网的职位页面,点击下一页,职位信息加载,但是浏览器的url的不变,说明数据不是发送get请求得到的. 我们不 ...