为什么不能在Thread实例中使用notifyAll()?

时间:2016-02-25 15:46:00

标签: java multithreading notify java-threads

我正在使用源代码分析器,指出不应在Thread实例中调用notifyAll()。我试图向管理层说明这一点,但我无法提出解释。有人能帮助我吗?

顺便说一句,这是继承的代码,所以我不负责设计决策!

2 个答案:

答案 0 :(得分:7)

听起来你看到的SONAR消息是this one

  

不应该在Thread实例上调用方法“wait(...)”,“notify()”和“notifyAll()”   鱿鱼:S2236

声纳对此进行了详细解释:

  

在Thread实例上,方法wait(...),notify()和notifyAll()仅可用,因为Java中的所有类都扩展了Object,因此会自动继承这些方法。但是有两个很好的理由不在Thread实例上调用这些方法:

     

这样做实在令人困惑。调用例如Thread上的wait(...)方法时真正期望的是什么?是暂停执行Thread还是等待对象监视器的获取?

     

在内部,JVM依赖这些方法来改变Thread的状态(BLOCKED,WAITING,...),因此调用它们会破坏JVM的行为。

同样,advice given in the Java API是:

  

建议应用程序不要在Thread实例上使用wait,notify或notifyAll。

通过锁定线程对象来完成内部线程管理。如果您自己的应用程序代码锁定线程,则可能会出现意外或混乱的行为。例如,当一个线程终止时,它会向等待它的每个线程发送一个通知。

在尝试评估问题的可能性时,我会查找线程可能会收到错误通知或因为被用作应用程序代码锁和内部JVM代码锁而错过通知的情况。 (这看起来可能很乏味。)根据代码,我还会查找由于锁定线程而导致的可能的一致性问题,而不是锁定线程访问的数据结构,并评估锁定方案是否有意义。如果代码是继承Thread的话,我想查看线程是否合并以及如何。

这个消息大多会让我想到,如果这个代码做了这个坏事,那还有什么可能做错了? SONAR消息只是暗示它在代码中发现了难闻的气味,因此您可以调查并查看问题的严重程度。

答案 1 :(得分:0)

你不应该对Thread进行子类化。这样做会打开一系列相当清楚的问题。使用wait / notifyAll不是一个很好的选择,因为并发库是在十多年前添加的,但在Thread上它特别糟糕,因为Thread类也使用wait / notify来达到自己的目的。