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()
. So today I will look into wait, notify in java program.
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.
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.
The example is following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
package studyjava; import java.util.ArrayList; import java.util.List; public class MyList { private static List<String> list = new ArrayList<String>(); public static void add() { list.add("anyString"); } public static int size() { return list.size(); } public static void main(String[] args) { try { Object lock = new Object(); ThreadA a = new ThreadA(lock); a.start(); Thread.sleep(50); ThreadB b = new ThreadB(lock); b.start(); } catch (InterruptedException e) { e.printStackTrace(); } } } class ThreadA extends Thread { private Object lock; public ThreadA(Object lock) { super(); this.lock = lock; } @Override public void run() { try { synchronized (lock) { if (MyList.size() != 5) { System.out.println("wait begin " + System.currentTimeMillis()); lock.wait(); System.out.println("wait end " + System.currentTimeMillis()); } } } catch (InterruptedException e) { e.printStackTrace(); } } } class ThreadB extends Thread { private Object lock; public ThreadB(Object lock) { super(); this.lock = lock; } @Override public void run() { try { synchronized (lock) { for (int i = 0; i < 10; i++) { MyList.add(); if (MyList.size() == 5) { lock.notify(); System.out.println("Send notification"); } System.out.println("Has added " + (i + 1) + " elements!"); Thread.sleep(1000); } } } catch (InterruptedException e) { e.printStackTrace(); } } } |
Output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
wait begin 1519888767472 Has added 1 elements! Has added 2 elements! Has added 3 elements! Has added 4 elements! Send notification Has added 5 elements! Has added 6 elements! Has added 7 elements! Has added 8 elements! Has added 9 elements! Has added 10 elements! wait end 1519888777527 |
In this example, Thread A need to wait a condition that list.size == 5, then start to excute. And Thread B add elements to list.
In order to make communication between two threads, we need wait() and notify() functions of class Object.
At first, Thread A start, and found (list.size() !=5), so it runs wait()
function into block status.
At the same time, Thread B start add elements into list, when the list.size ==5, Thread B runs notify() function to notify thread A.
What we need to know is that, although the Thread A is woke up when the list.size == 5, it still wait until Thread B ends its job. Because of keyword synchronized
, Thread A and Thread B cannot access the resourences at the same time, Thread A have to wait.
The disadvantage of this mechanism is that, for example, if the Thread B is excuted at first and added 5 elements at first before excuting Thread A, there will be a problem, contributing to a nevery wake up Thread A.