当前位置: 首页 > 面试题库 >

可以通知多次唤醒同一线程吗?

呼延俊良
2023-03-14
问题内容

想象一下,您在Java中有一个典型的生产者-
消费者模式。为了提高效率,您要使用notify()而不是notifyAll()在将新元素添加到队列时使用。如果两个生产者线程调用notify,是否保证将唤醒两个不同的正在等待的使用者线程?还是notify()彼此之间很快触发的两个s导致同一用户线程排队两次唤醒?我找不到该部分描述此工作原理的API。Java是否有一些原子内部操作可仅一次唤醒线程?

如果仅一个消费者正在等待,则第二个通知将丢失,这没有问题。


问题答案:

我的回答有一些特定于实现的信息。它基于我对Sun JVM和其他线程库行为的工作知识。

如果两个生产者线程调用notify,是否保证将唤醒两个不同的正在等待的使用者线程?

不它不是。不能保证会有任何消费者醒来。可以保证的是,如果有2个线程在等待,那么会将2个 不同的 线程放入运行队列。

还是notify()彼此之间很快触发的两个s导致同一用户线程排队两次唤醒?

否。两次notify()调用不会导致同一使用者线程两次排队。但是,这可能会导致一个线程被唤醒,并且可能没有其他线程在等待,因此第二个notify()调用可能什么都不做。当然,线程本可以被唤醒,然后又回到等待状态,这样就可以进行第二次notify()调用,但是我认为这不是您要的。

Java是否有一些原子内部操作可仅一次唤醒线程?

是。该Thread代码具有许多同步点。通知线程后,将其移出wait队列。将来的调用notify()将进入wait队列,但找不到该线程。

还有一点 很重要 。对于生产者/消费者html" target="_blank">模型,请始终确保您正在while循环测试条件。原因是存在与竞争者的竞争条件,这些竞争者被锁定但没有等待条件。

 synchronized (workQueue) {
     // you must do a while here
     while (workQueue.isEmpty()) {
         workQueue.wait();
     }
     workQueue.remove();
 }

Consumer1可能在等待workQueue
Consumer2可以synchronized在运行队列中被阻止。如果事情被放入workQueueworkQueue.notify()被调用。
Consumer2现在进入运行队列,但 落后于
Consumer1谁先行。这是一个常见的实现。所以,Consumer1去在将删除的项目workQueueConsumer2被通报的。
Consumer2必须再次测试是否workQueue为空,否则remove()将抛出异常,因为队列再次为空。有关比赛的更多详细信息,请参见此处。

同样重要的是要认识到已经记录了虚假while唤醒,因此该循环可以防止未经wait()调用而唤醒线程。

综上所述,如果您可以通过使用BlockingQueue其他答案中建议的减少生产者/消费者代码,则应该这样做。该BlockingQueue代码已经解决了所有这些问题。



 类似资料:
  • 我想做一个小练习来习惯等待/通知。我想做的是简单地启动一个线程,然后用等待让它进入睡眠状态,用通知唤醒它,多次。 我的代码是: 我希望这会是这样 相反,这样做: 所以。。。通知似乎没有唤醒打印机线程? 这不应该是一个死锁,因为通过等待,我释放了所有的锁,所以主服务器不应该有任何对打印机的锁,打印机应该能够唤醒并打印。 我做错了什么?

  • 本文向大家介绍Java多线程基础 线程的等待与唤醒(wait、notify、notifyAll),包括了Java多线程基础 线程的等待与唤醒(wait、notify、notifyAll)的使用技巧和注意事项,需要的朋友参考一下 本篇我们来研究一下 wait() notify() notifyAll() 。 DEMO1: wait() 与 notify() DEMO1 输出: 注意: 使用 wait

  • 我正在创建一个简单的web代理应用程序使用Java。基本上,main方法创建一个RequestReceiver对象,该对象具有侦听web浏览器http请求的ServerSocket。从ServerSocket.Accept()返回的套接字创建一个新的连接对象,并将其放入线程池中。

  • 本文向大家介绍怎么唤醒被阻塞的socket线程?相关面试题,主要包含被问及怎么唤醒被阻塞的socket线程?时的应答技巧和注意事项,需要的朋友参考一下 参考回答: 给阻塞时候缺少的资源

  • 我的Android手机上有一个蓝牙遥控快门。远程快门就像蓝牙键盘。 我的应用程序愉快地处理远程快门创建的键盘事件,但远程快门在90秒后进入睡眠状态,需要按一次键才能唤醒它,然后再发送下一次按键。 我需要一种机制来保持远程快门处于唤醒状态,这样我就不会失去第一次按键。(是的,我知道睡眠模式是为了节省能量,但我需要低延迟)。 我尝试以客户端和服务器的身份连接到设备,希望我可以将OutputStream