0

在我的应用程序的某个时刻,我想让我的主线程(即当前正在执行的线程)休眠一段时间或直到后台完成(并唤醒它),以先到者为准。

这是我所做的(我认为它会起作用,但没有)

public static void main(String args[])
{
    // .... other stuff ...

    // show a splash screen
    // just think of this as an image
    showPlashScreen(): 
    new Thread(new Runnable()
    {
          public void run()
          {
                // do some work here

                // notify everyone after the work is done
                Thread.currentThread().notifyAll();
          }
    }).start();

    // now make the current thread to wait for the background
    // or for at most 1000
    Thread.currentThread().wait(1000);
    disposeSplashScreen();

    // ... other stuff ....
}

执行这个,我不断得到java.lang.IllegalMonitorStateException

(部分)堆栈跟踪:

Caused by: java.lang.IllegalMonitorStateException
    at java.lang.Object.wait(Native Method)

.... <cut> ....

Exception in thread "Thread-7" java.lang.IllegalMonitorStateException
    at java.lang.Object.notifyAll(Native Method)
4

4 回答 4

5

为了能够调用 notify(),您需要在同一个对象上进行同步。

synchronized (someObject) {
    someObject.wait();
}

/* different thread / object */
synchronized (someObject) {
    someObject.notify();
}
于 2013-05-01T06:49:15.983 回答
2

首先,不要在对象上使用wait和。这被用作内部信号通道,因此您的代码最终可能会混淆 JRE 代码,反之亦然。notifyThread

其次,它不起作用的一个原因是您的主线程正在等待自己,而后台线程正在通知自己——它们是不同的对象!

第三,要使用notify()wait()你需要先在显示器上同步。此外,wait您通常会使用循环来检查条件,以处理虚假唤醒。

第四,如果你真的在等待线程结束,你可以join改用:

Thread thread = new Thread(new Runnable()
{
    @Override public void run()
    {
        // do some work here
    }
});
thread.start();

// Do something else

thread.join(1000);

(不幸的是join,它没有表明它是否由于超时或线程完成而返回 - 但您可以在之后检查线程状态。)

或者,使用其中一种更高级别的构造来java.util.concurrent代替 - 正如 JB Nizet 所建议的那样,它们通常不那么繁琐。

于 2013-05-01T06:44:39.347 回答
1

您为wait()and使用了两个不同的对象notifyAll():主线程在主线程上等待,而后台线程在后台线程上通知。您应该为这两个调用使用一个共享的最终对象。您还应该在此共享对象的同步块中等待并通知,如这两种方法的 javadoc 中所述。并且应该只在某些条件发生变化的情况下退出等待状态,以避免虚假唤醒,如 javadoc 中所述。

但是 wait() 和 notifyAll() 太低级了,很难正确使用。您应该改用信号量等更高级别的抽象。

于 2013-05-01T06:46:20.500 回答
0

如您所愿put the current thread to sleep while waiting for another thread,您现在的做法并不意味着相同的事情,即wait and notifiy方法。

这些方法旨在用于同步对象而不是线程。

对于线程,您应该使用join 方法查看

于 2013-05-01T06:51:23.520 回答