如果一个人在谷歌上搜索“notify()和notifyAll()之间的区别”,那么会跳出很多解释(撇开javadoc段落)。这都归结于被唤醒的等待线程的数量:notify()中有一个,notifyAll()中有所有线程。
然而(如果我确实理解了这些方法之间的区别),只有一个线程总是被选择用于进一步的监视采集;第一种情况是VM选择的线程,第二种情况是系统线程调度程序选择的线程。程序员不知道它们的确切选择过程(在一般情况下)。
那么notify()和notifyAll()之间有什么有用的区别呢?我遗漏了什么吗?
notify()让您编写比notifyAll()更有效的代码。
考虑下面这段从多个并行线程执行的代码:
synchronized(this) {
while(busy) // a loop is necessary here
wait();
busy = true;
}
...
synchronized(this) {
busy = false;
notifyAll();
}
可以通过使用notify()来提高效率:
synchronized(this) {
if(busy) // replaced the loop with a condition which is evaluated only once
wait();
busy = true;
}
...
synchronized(this) {
busy = false;
notify();
}
在有大量线程的情况下,或者如果等待循环条件的计算成本很高,notify()将比notifyAll()快得多。例如,如果你有1000个线程,那么999个线程将在第一个notifyAll()之后被唤醒和评估,然后是998,然后是997,依此类推。相反,使用notify()解决方案,只会唤醒一个线程。
使用notifyAll()当你需要选择哪个线程将做下一步工作:
synchronized(this) {
while(idx != last+1) // wait until it's my turn
wait();
}
...
synchronized(this) {
last = idx;
notifyAll();
}
Finally, it's important to understand that in case of notifyAll(), the code inside synchronized blocks that have been awakened will be executed sequentially, not all at once. Let's say there are three threads waiting in the above example, and the fourth thread calls notifyAll(). All three threads will be awakened but only one will start execution and check the condition of the while loop. If the condition is true, it will call wait() again, and only then the second thread will start executing and will check its while loop condition, and so on.
当你调用wait()的“对象”(期望对象锁)、实习生这将释放锁,物体和帮助的其他线程锁在这个“对象”,在这种情况下,将会有超过1线程等待“资源/对象”(考虑到其他线程也发布了等待上面相同的对象,将会有一个线程的方式填补资源/对象并调用通知/ notifyAll)。
在这里,当您(从进程/代码的同一/另一端)发出同一对象的通知时,这将释放一个阻塞和等待的单个线程(不是所有等待的线程——这个释放的线程将由JVM thread Scheduler挑选,对象上的所有锁获取进程与常规进程相同)。
如果只有一个线程共享/处理这个对象,那么可以在wait-notify实现中单独使用notify()方法。
如果您处于基于业务逻辑的多个线程对资源/对象进行读写的情况,那么您应该使用notifyAll()
现在我正在寻找JVM是如何识别和打破等待线程时,我们发出通知()在一个对象…