Java如何使用wait/notify实现线程间通信


本文小编为大家详细介绍“Java如何使用wait/notify实现线程间通信”,内容详细,步骤清晰,细节处理妥当,希望这篇“Java如何使用wait/notify实现线程间通信”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体。线程间的通信就是成为整体的必用方案之一,使用线程间进行通信后,系统之间的交互性会更强大,大大提高CPU利用率。等待/通知机制(1)不使用等待/通知机制实现线程间通信样例代码如下:执行结果:分析:程序运行后的效果如上图所示:虽然 ThreadA 和 ThreadB 实现了通信,但有一个弊端就是,ThreadB 需要不停地通过 while 语句轮询机制来检测某一个条件,这样会浪费CPU资源。如果轮询的时间间隔很小,更浪费CPU资源;如果轮询的时间间隔很大,有可能会取不到想要得到的数据。所以就需要有一种机制来实现减少CPU的资源浪费,而且还可以实现在多个线程间通信,它就是 “等待/通知”(wait/notify)机制。(2)什么是等待/通知机制等待/通知机制在生活中比比皆是,比如在就餐时就会出现厨师和服务员之间的交互要在 “菜品传递台”上,在这期间会有几个问题:问题一:厨师做完一道菜的时间不确定,所以厨师将菜品放到“菜品传递台”上的时间也不确定。问题二:服务员取到菜的时间取决于厨师,所以服务员就有“等待”(wait)的状态。问题三:服务员如何能取到菜呢?这又得取决于厨师,厨师将菜放在“菜品传递台”上,其实就相当于一种通知(notfiy),这时服务员才可以拿到菜并交给就餐者。问题四:在这个过程中出现了“等待/通知”机制。(3)等待/通知机制的实现方法wait()的作用是使当前执行代码的线程进行等待,wait()方法是Object类的方法,该方法用来将当前线程置入“预执行队列”中,并且在wait()所在的代码行处停止执行,直到接到通知或被中断为止。在调用wait()之前,线程必须获取该对象的对象级别锁,即只能在同步方法或同步块中调用wait()方法。在执行wait()方法后,当前线程释放锁。在从wait()返回前,线程与其他线程竞争重新获得锁。如果调用wait()时没有持有适当的锁,则抛出 IllegalMonitorStateException,它是 RuntimeException的一个子类,因此,不需要 try-catch 语句进行捕捉异常。方法notify()也要在同步方法或同步块中调用,即在调用前,线程也必须获取该对象的对象级别锁。如果调用notify()时没有持有适当的锁,也会抛出IllegalMonitorStateException。该方法用来通知那些可能等待该对象的对象锁的其他线程,如果有多个线程等待,则由线程规划器随机挑选出其中一个呈wait状态的线程,对其发出通知notify,并是它等待获取该对象的对象锁。需要说明是:在执行notify()方法后,当前线程不会马上释放该对象锁,呈wait状态的线程也并不能马上获取该对象锁,要等到执行notify()方法的线程将程序执行完,也就是退出synchronized代码块后,当前线程才会释放锁,而呈wait状态所在的线程才可以获取该对象锁。当第一个获得了该对象锁的wait线程运行完毕以后,它会释放掉该对象锁,此时如果该对象没有再次使用notify语句,则几遍该对象已经空闲,其他wait状态等待的线程由于没有得到该对象的通知,还会继续阻塞在wait状态,直到这个对象发出一个notify 或 notifyAll。总结一下:wait:使线程停止运行notify:使停止的线程继续运行验证1:在调用wait()之前,线程必须获取该对象的对象级别锁,即只能在同步方法或同步块中调用wait()方法。如果调用wait()时没有持有适当的锁,则抛出IllegalMonitorStateException。执行结果:验证2:调用了wait(),线程会在调用wait()所在的代码行处停止执行,直到接到通知或被中断为止。执行结果:结果分析:线程执行了wait()方法后,程序就停止不前,不继续向下运行了。如何使呈等待wait状态的线程继续运行呢?答案就是使用notify()方法。执行结果:
开始 wait,Time=[1659520582642]
开始 notify,Time=[1659520585652]
结束 notify,Time=[1659520585652]
结束 wait,Time=[1659520585656]验证3:notify方法用来通知那些可能等待该对象的对象锁的其他线程,如果有多个线程等待,则有线程规划器随机挑选出其中一个呈wait状态的线程,对其发出通知notify,并使它等待获取该对象的对象锁。执行结果:结果分析:可以看到处于wait状态的ThreadC5B线程被通知到继续执行,而ThreadC5C线程则一直将处于wait状态,无法继续执行。倘若我们将ThreadC5A线程中的 lock.notify() 改写为 lock.notifyAll(),则结果就不一样,如图所示:发现ThreadC5B 和 ThreadC5C免费云主机域名线程均获取到了对象锁,完成了wait()后面代码的执行。验证4:上图的结果还可以验证在执行notify()方法后,当前线程不会马上释放该对象锁,呈wait状态的线程也并不能马上获取该对象锁,要等到执行notify()方法的线程将程序执行完,也就是退出synchronized代码块后,当前线程才会释放锁,而呈wait状态所在的线程才可以获取该对象锁。结果分析:可以看出 ThreadC5A 线程在list 长度为5的时候,则通知了 ThreadC5B 和 ThreadC5C 两个处于wait状态的线程,但是 ThreadC5B 和 ThreadC5C 线程并没有立马继续执行,因为此时 ThreadC5A 并没有释放对象锁,而是继续执行 synchronized的代码块,直到退出synchronized代码块后,ThreadC5A 才释放了对象锁,ThreadC5B 和 ThreadC5C 获得对象锁,才得以继续执行后续代码。读到这里,这篇“Java如何使用wait/notify实现线程间通信”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注百云主机行业资讯频道。

相关推荐: 如何用c语言求出给定范围内的所有质数

这篇文章主要讲解了“如何用c语言求出给定范围内的所有质数”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何用c语言求出给定范围内的所有质数”吧!程序功能:输入一个整数,要求打印出这个整数以内的所有质数。程序示例…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

(0)
打赏 微信扫一扫 微信扫一扫
上一篇 02/26 23:14
下一篇 02/26 23:14

相关推荐