本文主要介绍Java notify和notifyAll的知识,这里整理详细的资料来说明notify 和NotifAll的区别,有需要的小伙伴可以参考下 经常在往上逛,关于在java中notify和notifyAll,经常有人有以下的说法: notify只会通知一个在等待的对象,而notifyAll会通知所有在等待的对象,并且所有对象都会继续运行 并且,好像都有例子可以证明。上面的说法,可以说对,也可以说不对。究其原因,在于其中有一点很关键,官方的说法如下所示: wait,notify,notifyAll: 此方法只应由作为此对象监视器的所有者的线程来调用。通过以下三种方法之一,线程可以成为此对象监视器的所有者 以上说法,摘自javadoc。意思即,在调用中,必须持有对象监视器(即锁),我们可以理解为需要在synchronized方法内运行。那么由此话的隐含意思,即如果要继续由同步块包含的代码块,需要重新获取锁才可以。这句话,在javadoc中这样描述: wait 此方法导致当前线程(称之为 T)将其自身放置在对象的等待集中,然后放弃此对象上的所有同步要求。出于线程调度 即必须重新进行获取锁,这样对于notifyAll来说,虽然所有的线程都被通知了。但是这些线程都会进行竞争,且只会有一个线程成功获取到锁,在这个线程没有执行完毕之前,其他的线程就必须等待了(只是这里不需要再notifyAll通知了,因为已经notifyAll了,只差获取锁了)有如下一个代码,可以重现这个现象。 首先,定义一个可以运行的线程类,如下所示:
注意上面的run方法内部,我们在wait()之后,打印一句话,然后将当前代码,暂停30秒。关于sleep方法,是这样描述的: 然后,定义一个main方法来运行这些线程,如下所示:
我们定义了10个线程,然后全部运行之。因为有wait,10个线程都会在打印出 “开始运行”之后等待。然后main方法调用notifyAll。这里的输出就会出现如下的输出: 线程-> 0 等待中 在上面的输出中,在wait之后,只有一个线程输出了”在运行了”语句,并且在一段时间内(这里为30秒),不会有其他输出。即表示,在当前代码持有锁之间,其他线程是不会输出的。 最后结论就是:被wait的线程,想要继续运行的话,它必须满足2个条件: 由其他线程notify或notifyAll了,并且当前线程被通知到了 经过和其他线程进行锁竞争,成功获取到锁了2个条件,缺一不可。其实在实现层面,notify和notifyAll都达到相同的效果,会有一个线程继续运行。但notifyAll免去了,线程运行完了通知其他线程的必要,因为已经通知过了。什么时候用notify,什么时候使用notifyAll,这就得看实际的情况了。 以上就是对Java notify和NotifyAll的资料整理,后续继续补充相关资料谢谢大家对本站的支持! |