在我的应用程序中的某个时刻,我想让我的主线程(即,当前正在执行的线程)暂停一段时间或者直到后台完成(并唤醒它),以先到者为准。
这是我所做的(我认为可行,但没有)
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
(部分)stacktrace:
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)
答案 0 :(得分:4)
为了能够调用notify(),您需要在同一个对象上进行同步。
synchronized (someObject) {
someObject.wait();
}
/* different thread / object */
synchronized (someObject) {
someObject.notify();
}
答案 1 :(得分:2)
首先,不要在wait
个对象上使用notify
和Thread
。这被用作内部信令通道,因此您的代码最终会混淆JRE代码,反之亦然。
其次,它不起作用的一个原因是你的主线程在等待自己,后台线程正在通知自己 - 那些是不同的对象!
第三,要使用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建议的那样。
答案 2 :(得分:1)
您正在为wait()
和notifyAll()
使用两个不同的对象:主线程在主线程上等待,而后台线程在后台线程上通知。您应该为两个调用使用共享的最终对象。您还应该在此共享对象的同步块中等待并通知,如这两种方法的javadoc中所述。并且只应退出等待状态,其中一些条件已经改变,以避免虚假的唤醒,如javadoc中所述。
但是wait()和notifyAll()太低级,太难以正确使用。您应该使用更高级别的抽象,例如信号量。
答案 3 :(得分:0)
如您所希望put the current thread to sleep while waiting for another thread
,您现在的表现方式并不适用于wait and notifiy
方法。
这些方法适用于同步对象而非线程。
对于线程,您应该使用加入方法。 Check Out