java 中的 Object 类包含三种最终方法,允许线程通信资源的锁定状态. 这些方法是 wait(), **notify()**和 notifyAll(). 所以今天我们将在 java 程序中研究等待,通知和 notifyAll。
在 Java 中等待、通知和通知
The current thread which invokes these methods on any object should have the object monitor else it throws java.lang.IllegalMonitorStateException exception.
等待
对象等待方法有三种差异性,一个是无限期地等待任何其他线程调用通知或通知对象上的所有方法来唤醒当前线程。
通知
通知方法只唤醒一个在对象上等待的线条,而那个线条开始执行,所以如果有多个线条在等待一个对象,这个方法只会唤醒其中一个线条。
通知
notifyAll 方法唤醒在对象上等待的所有线程,虽然其中一个将首先处理取决于操作系统的实现。这些方法可以用来实现 [生产者消费者问题](/community/tutorials/java-blockingqueue-example Java BlockingQueue 实例实施生产者消费者问题
)在消费者线程等待在队列中的对象,生产者线程将对象排队并通知等待线程。
信息
java bean 类,在其中线程将工作,并调用等待和通知方法。
1package com.journaldev.concurrency;
2
3public class Message {
4 private String msg;
5
6 public Message(String str){
7 this.msg=str;
8 }
9
10 public String getMsg() {
11 return msg;
12 }
13
14 public void setMsg(String str) {
15 this.msg=str;
16 }
17
18}
服务员
等待其他线程调用通知方法来完成其处理的类别. 请注意,服务器线程使用同步区块在消息对象上拥有监视器。
1package com.journaldev.concurrency;
2
3public class Waiter implements Runnable{
4
5 private Message msg;
6
7 public Waiter(Message m){
8 this.msg=m;
9 }
10
11 @Override
12 public void run() {
13 String name = Thread.currentThread().getName();
14 synchronized (msg) {
15 try{
16 System.out.println(name+" waiting to get notified at time:"+System.currentTimeMillis());
17 msg.wait();
18 }catch(InterruptedException e){
19 e.printStackTrace();
20 }
21 System.out.println(name+" waiter thread got notified at time:"+System.currentTimeMillis());
22 //process the message now
23 System.out.println(name+" processed: "+msg.getMsg());
24 }
25 }
26
27}
通知
一个类将处理在消息对象,然后调用通知方法唤醒等待消息对象的线程. 请注意,同步区块用于拥有消息对象的监视器。
1package com.journaldev.concurrency;
2
3public class Notifier implements Runnable {
4
5 private Message msg;
6
7 public Notifier(Message msg) {
8 this.msg = msg;
9 }
10
11 @Override
12 public void run() {
13 String name = Thread.currentThread().getName();
14 System.out.println(name+" started");
15 try {
16 Thread.sleep(1000);
17 synchronized (msg) {
18 msg.setMsg(name+" Notifier work done");
19 msg.notify();
20 // msg.notifyAll();
21 }
22 } catch (InterruptedException e) {
23 e.printStackTrace();
24 }
25
26 }
27
28}
等待测试
测试类将创建多条服务员和通知器线程并启动它们。
1package com.journaldev.concurrency;
2
3public class WaitNotifyTest {
4
5 public static void main(String[] args) {
6 Message msg = new Message("process it");
7 Waiter waiter = new Waiter(msg);
8 new Thread(waiter,"waiter").start();
9
10 Waiter waiter1 = new Waiter(msg);
11 new Thread(waiter1, "waiter1").start();
12
13 Notifier notifier = new Notifier(msg);
14 new Thread(notifier, "notifier").start();
15 System.out.println("All the threads are started");
16 }
17
18}
当我们召唤上面的程序时,我们会看到下面的输出,但程序不会完成,因为有两个线程在等待消息对象和 notify() 方法中醒来,只有其中一个线程,另一个线程还在等待通知。
1waiter waiting to get notified at time:1356318734009
2waiter1 waiting to get notified at time:1356318734010
3All the threads are started
4notifier started
5waiter waiter thread got notified at time:1356318735011
6waiter processed: notifier Notifier work done
如果我们评论 notify() 调用,并在 Notifier 类别中不评论 notifyAll() 调用,以下将是产生的输出。
1waiter waiting to get notified at time:1356318917118
2waiter1 waiting to get notified at time:1356318917118
3All the threads are started
4notifier started
5waiter1 waiter thread got notified at time:1356318918120
6waiter1 processed: notifier Notifier work done
7waiter waiter thread got notified at time:1356318918120
8waiter processed: notifier Notifier work done
由于 notifyAll() 方法唤醒 Waiter 线程和程序完成和结束后执行. 这是等待,通知和 notifyAll 在 java 的所有。