Java Thread wait, notify and notifyAll Example
Java线程中的使用的wait,notify和nitifyAll方法示例.
The Object class in java contains three final methods that allows threads to communicate about the lock status of a resource. These methods
are wait(), notify() and notifyAll().
方法:wait,notify和notifyAll都是Object类中的方法而且还是final类型的,不允许重载。这三个方法主要是为了线程间通信使用,通信采用的机制是锁机制。
The current thread which invokes these methods on any object should have the object monitor else it throws java.lang.IllegalMonitorStateException exception.
当前线程调用这些方法需要try,catch,因为他会抛异常。
wait
Object wait methods has three variance, one which waits indefinitely for any other thread to call notify or notifyAll method on the object to wake up the current thread. Other two variances puts the current thread in wait for specific amount of time before they wake up.
线程wait有三种含义,一种是wait之后等到其他线程去唤醒,可以使用notify或者是notifyaAll方法,另一种是自己指定wait的时间,时间到了自己唤醒自己。
notify
notify method wakes up only one thread waiting on the object and that thread starts execution. So if there are multiple threads waiting for an object, this method will wake up only one of them. The choice of the thread to wake depends on the OS implementation of thread management.
notify方法一次只能唤醒一个线程,然后唤醒线程得以执行。因此在多线程中这种方式一次只能唤醒一个,具体唤醒那个依赖于OS线程管理的实现。
notifyAll
notifyAll method wakes up all the threads waiting on the object, although which one will process first depends on the OS implementation.
方法notifyAll唤醒所有使用这个对象锁的线程,只是先后顺序依赖于OS的实现。
These methods can be used to implement producer consumer problem where consumer threads are waiting for the objects in Queue and producer threads put object in queue and notify the waiting threads.
一般情况这个方法使用在生产者和消费者的问题上,消费线程等待消费队列中的商品,生产者则生产这些商品最后丢带队列中,以供消费者使用。
Let’s see an example where multiple threads work on the same object and we use wait, notify and notifyAll methods
一起看个关于多线程的例子,使用同一个对象去wait,notify和notifyAll方法。
Message.java
1 package com.journaldev.concurrency; 2 3 public 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 }
Waiter
A class that will wait for other threads to invoke notify methods to complete it’s processing. Notice that Waiter thread is owning monitor on Message object using synchronized block.
1 package com.journaldev.concurrency; 2 3 public 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 }
Notifier
A class that will process on Message object and then invoke notify method to wake up threads waiting for Message object. Notice that synchronized block is used to own the monitor of Message object.
这个类使用message对象去调用notify方法,然后唤醒使用message对象wait的线程,注意,这里同样使用了Message对象去作为sysnchronized的锁。
Notifier.java
1 package com.journaldev.concurrency; 2 3 public 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 }
WaitNotifyTest
Test class that will create multiple threads of Waiter and Notifier and start them.
测试上述内容在多线程中调用waiter和notifier实现等待和唤醒。
1 package com.journaldev.concurrency; 2 3 public 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 }
1 waiter waiting to get notified at time:1356318734009 2 waiter1 waiting to get notified at time:1356318734010 3 All the threads are started 4 notifier started 5 waiter waiter thread got notified at time:1356318735011 6 waiter processed: notifier Notifier work done
1 waiter waiting to get notified at time:1356318917118 2 waiter1 waiting to get notified at time:1356318917118 3 All the threads are started 4 notifier started 5 waiter1 waiter thread got notified at time:1356318918120 6 waiter1 processed: notifier Notifier work done 7 waiter waiter thread got notified at time:1356318918120 8 waiter processed: notifier Notifier work done
Since notifyAll() method wake up both the Waiter threads and program completes and terminates after execution.