Java Thread等待,通知和notifyAll示例
java中的Object类包含三个最终方法,这些方法允许线程就资源的锁定状态进行通信。
这些方法是wait(),notify()和notifyAll()。
因此,今天我们将研究java程序中的wait,notify和notifyAll。
用Java等待,通知和notifyAll
当前在任何对象上调用这些方法的线程都应具有对象监视器,否则它将引发java.lang.IllegalMonitorStateException异常。
等待
对象等待方法具有三种变化,一种无限期等待其他线程调用对象上的notify或者notifyAll方法来唤醒当前线程。
其他两个差异会使当前线程在唤醒之前等待特定的时间。
通知
notify方法仅唤醒一个正在等待该对象的线程,并且该线程开始执行。
因此,如果有多个线程在等待一个对象,则此方法将仅唤醒其中一个。
唤醒线程的选择取决于线程管理的OS实现。
notifyAll
notifyAll方法唤醒等待对象的所有线程,尽管首先处理哪个线程取决于OS的实现。
这些方法可用于实现生产者消费者问题,其中消费者线程正在等待Queue中的对象,而生产者线程将对象放入队列中并通知正在等待的线程。
让我们看一个示例,其中多个线程在同一个对象上工作,我们使用wait,notify和notifyAll方法。
信息
线程将在其上工作的Java bean类,并调用wait和notify方法。
package com.theitroad.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; } }
服务
该类将等待其他线程调用notify方法以完成其处理。
注意,Waiter线程正在使用同步块在Message对象上拥有监视器。
package com.theitroad.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()); } } }
通知者
一个将在Message对象上处理,然后调用notify方法以唤醒等待Message对象的线程的类。
请注意,同步块用于拥有Message对象的监视器。
package com.theitroad.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(); } } }
WaitNotifyTest
测试类,该类将创建Waiter和Notifier的多个线程并启动它们。
package com.theitroad.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类中注释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线程,因此程序在执行后完成并终止。
这一切都可以等待,可以在Java中进行notify和notifyAll。