简体   繁体   English

如果在Thread上调用java wait(),则该方法也会在run()方法终止时退出

[英]if java wait() is called on a Thread, the method exits also on run() method termination

I'm puzzled with a particular use case of the wait() method. 我对wait()方法的特定用例感到困惑。
According with javadoc, wait should end when one of the following condition happens: 根据javadoc,当出现下列情况之一时,wait应该结束:

  • another thread invokes notify or notifyAll (ok, see javadoc for a detail on notify but this is not relevant for this question) 另一个线程调用notify或notifyAll(好的,请参阅javadoc以获取有关通知的详细信息,但这与此问题无关)
  • another thread interrupts this (waiting) thread 另一个线程中断这个(等待)线程
  • a timeout expires (if using the wait version with timeout) 超时到期(如果使用带超时的等待版本)

In the case in which the object i'm waiting on is itself a Thread, it happens that the wait() exits even if no notify() has been called, and no one of the above conditions holds. 在我正在等待的对象本身就是一个Thread的情况下,即使没有调用notify(),并且上述条件中没有一个成立,也会发生wait()退出。 But it happens when the Thread.run() method ends. 但是当Thread.run()方法结束时会发生这种情况。 While this behavior may make sense, shouldn't it be documented inside of Thread javadoc? 虽然这种行为可能有意义,但不应该在Thread javadoc中记录吗? I find it very confusing also because it overlaps with join() behavior. 我发现它也很混乱,因为它与join()行为重叠。

This is my test code: 这是我的测试代码:

public static class WorkerThread extends Thread {

    @Override public void run() {

        try{
           System.out.println("WT: waiting 4 seconds");
           Thread.sleep(4000);

           synchronized (this) {
            notify();
           }

           System.out.println("WT: waiting for 4 seconds again");
           Thread.sleep(4000);
           System.out.println("WT: exiting");

        } catch (InterruptedException ignore) {
            ignore.printStackTrace();
        }

    }

}

public static void main (String [] args) throws InterruptedException {

    WorkerThread w = new WorkerThread();

    w.start();

    synchronized(w) {
        w.wait();
        System.out.println("MT: The object has been notified by the thread!");
    }

    synchronized(w) {

        w.wait(); //THIS FINISHES WITHOUT notify(), interrupt() OR TIMEOUT!

        System.out.println("MT: The thread has been notified again!");
    }

}

It is documented since Java 7, in the documentation of the join() method : 自Java 7以来,在join()方法文档中记录了它

As a thread terminates the this.notifyAll method is invoked. 当一个线程终止时,将调用this.notifyAll方法。 It is recommended that applications not use wait, notify, or notifyAll on Thread instances. 建议应用程序不要在Thread实例上使用wait,notify或notifyAll。

It is a common anti-pattern to extend Thread directly. 直接扩展Thread是一种常见的反模式。 The problem is you can have all sorts of unintended consequences as Thread is a complex class. 问题是你可以有各种意想不到的后果,因为Thread是一个复杂的类。 One thing it does is notify threads trying to join() the thread when it stops. 它做的一件事是通知线程在停止时试图加入()线程。 This has the effect of notifying any thread waiting on that thread object. 这具有通知等待该线程对象的任何线程的效果。

A common Java puzzler is to miss use a class which extends Thread. 一个常见的Java益智游戏是错过使用扩展Thread的类。

BTW While using wait()/notify() has been old school for more than 9 years now, you can still use them in rare situations. BTW虽然使用wait()/ notify()已经老了9年多了,但你仍然可以在极少数情况下使用它们。 If you do you should change the state of something in the notify() block and wait for that state change when you wait(). 如果这样做,您应该更改notify()块中某些内容的状态,并在wait()时等待该状态更改。 This is because if you call notify before wait, it is lost and wait() can exist spuriously, even if you don't extend thread. 这是因为如果你在等待之前调用notify,它就会丢失并且wait()可能会伪造,即使你没有扩展线程。

如果您想要可预测和可控制的等待/通知行为,请在线程和等待它的方法之间共享一个Object。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM