I often browse up. Regarding notify and notifyAll in java, people often have the following statements:
notify will only notify an object waiting, while notifyAll will notify all objects waiting, and all objects will continue to run.
And, it seems that there are examples to prove it. The above statement can be said to be correct or not. The reason is that one of them is very important. The official statement is as follows:
wait,notify,notifyAll:
This method should only be called by a thread that is the owner of this object monitor. A thread can become the owner of this object monitor in one of three ways:
By executing the synchronous instance method of this object.
The body of the synchronized statement is executed by executing the synchronized statement on this object.
For objects of type Class, you can execute synchronous static methods of the class.
Only one thread has an object monitor at a time.
The above statement is excerpted from javadoc. This means that in the call, the object monitor (i.e., lock) must be held, which we can understand as running within the synchronized method. Then the implicit meaning of this statement is that if you want to continue the code block contained in the synchronization block, you need to re-acquire the lock. This sentence is described in javadoc:
wait
This method causes the current thread (called T) to place itself in the waiting set of the object and then abandon all synchronization requirements on this object. For thread scheduling purposes, thread T is disabled and is in hibernation before one of the following four situations occurs:
Some other thread calls the notify method of this object, and thread T happens to be optionally selected as the wake-up thread.
Some other thread calls the notifyAll method of this object.
Some other thread interrupts thread T.
Approximately the specified actual time has been reached. However, if timeout is zero, the actual time is not taken into account and the thread will wait until notification is obtained.
Then, thread T is deleted from the object's waiting set and thread scheduling is performed again. The thread then competes with other threads in a conventional way to obtain the right to synchronize on the object; once control over the object is obtained, all its synchronization declarations on the object will be restored to their previous state, which is to call wait
The situation when the method is. Thread T then returns from the call to the wait method. Therefore, when returning from the wait method, the synchronization state of the object and thread T is exactly the same as when calling the wait method.
That is, the lock must be re-acquisitioned, so that for notifyAll, all threads have been notified. However, these threads will compete, and only one thread will successfully acquire the lock. Before this thread is executed, other threads must wait (but there is no need to notifyAll notification here, because it is notifyAll, and it is only necessary to acquire the lock). There is the following code that can reproduce this phenomenon.
First, define a thread class that can run, as follows:
private static final Object obj = new Object(); static class R implements Runnable { int i; R(int i) { this.i = i; } public void run() { try { synchronized(obj) { System.out.println("Thread-> " + i + " Waiting"); obj.wait(); System.out.println("Thread-> " + i + " Running"); Thread.sleep(30000); } } catch(Exception e) { e.printStackTrace(); } } } Pay attention to the inside of the run method above. After waiting(), we print a sentence, and then pause the current code for 30 seconds. Regarding the sleep method, it is described as follows:
The thread does not lose ownership of any monitors.
That is, the lock is still held.
Then, define a main method to run these threads as follows:
Thread[] rs = new Thread[10]; for(int i = 0;i < 10;i++) { rs[i] = new Thread(new R(i)); } for(Thread r : rs) { r.start(); } Thread.sleep(5000); synchronized(obj) { obj.notifyAll(); }We define 10 threads and then run them all. Because there is wait, 10 threads will wait after printing out "Start Run". Then the main method calls notifyAll. The output here will appear as follows:
Thread-> 0 Waiting for thread-> 4 Waiting for thread-> 5 Waiting for thread-> 3 Waiting for thread-> 2 Waiting for thread-> 1 Waiting for thread-> 6 Waiting for thread-> 7 Waiting for thread-> 8 Waiting for thread-> 9 Waiting for thread-> 9 Running
...No other output within 30 seconds
In the above output, after wait, only one thread outputs the "running" statement, and for a period of time (30 seconds here), there will be no other output. That is to say, other threads will not output between the locks held by the current code.
The final conclusion is: If the waiting thread wants to continue running, it must meet two conditions:
The other thread notify or notifyAll has been notified, and the current thread has been notified.
After competing with other threads to lock, two conditions were successfully obtained for locking, and neither of them was missing. In fact, at the implementation level, notify and notifyAll achieve the same effect, and a thread will continue to run. But notifyAll is exempted. The need to notify other threads after the thread is running, because it has been notified. When to use notify and when to use notifyAll, it depends on the actual situation.
The above is a compilation of the information for Java notify and NotifyAll. We will continue to add relevant information in the future. Thank you for your support for this website!