sof*_*ver 8 java multithreading synchronized wait
我在java.lang.Object中使用wait()的定时版本,并观察到它在两种不同的场景中的行为不同.
场景1:在Thread中使用run()的默认定义
public static void main (String[] args) throws InterruptedException {
Thread t = new Thread();
t.start();
System.out.print("X");
synchronized(t) { t.wait(10000);}
System.out.print("Y");
}
Run Code Online (Sandbox Code Playgroud)
关于scenario1的问题:我遇到了X和Y之间的延迟.这是因为我从main调用wait()(即使在t上)因此正在使用主线程的调用堆栈,而不是第二个线程?
场景2:动态 子类化线程以覆盖run()以打印内容.
public static void main (String[] args) throws InterruptedException {
Thread t = new Thread() {public void run()
{System.out.print("I am the second thread.");}};
t.start();
System.out.print("X");
synchronized(t) { t.wait(10000);}
System.out.print("Y");
}
Run Code Online (Sandbox Code Playgroud)
关于场景2的问题:我没有遇到任何延迟!是什么改变只是因为我已经覆盖了run()?现在,每次我运行该程序时,它立即打印出"XI am the second thread.Y",无论如何都没有任何延迟!wait()的效果在哪里消失了?
实际上你已经遇到了为什么你不应该调用wait或notify(All)在线程上(参见JavaDocs for Thread).在内部,Thread使用wait和notifyAll来实现Thread.join(),所以在第二种情况下发生的是线程进入等待,但随后另一个线程死掉并调用notifyAll(),它唤醒你的主线程.
使用Thread.sleep,如果你只是想等待经过的时间,使用Thread.join,如果你真的想等待线程终止.此外,阅读JavaDoc中Object的正确使用wait,notify以及notifyAll.
Run Code Online (Sandbox Code Playgroud)public final void join(long millis) throws InterruptedException此线程最多等待毫秒毫秒.超时为0意味着永远等待.此实现使用this.wait调用this.isAlive的循环.当一个线程终止时,将调用this.notifyAll方法.建议应用程序不要在Thread实例上使用wait,notify或notifyAll.
关于线程完成如何发送notifyAll的解释是相关且正确的,我的+1。我将尝试添加一些关于为什么这是相关的信息。
你打电话时
synchronized(t) { t.wait(10000);}
Run Code Online (Sandbox Code Playgroud)
在主线程中,是主线程在进行等待。t是主线程正在等待的监视器。您认为这应该使您的t线程休眠的期望是错误的。
这里的监视器(被锁定的共享对象,恰好是t)用于在不同线程之间进行通信,一个线程在监视器上调用notifyAll,并且在监视器上等待的其他线程接收通知。您可以将监视器视为共享通信点。
在您的第一个示例中,线程 t 立即启动并完成(因为它没有任何事情可做)。线程在主线程开始等待之前完成并发送通知,因此您会看到等待超时之前的延迟。
在第二个示例中,线程 t 有一些内容要打印,它与主线程之间存在竞争条件。这是一场混战,首先发生什么取决于时机的意外。您看到的是,线程t现在必须向控制台打印一行,因此它设法保持足够长的忙碌状态,以便在主线程开始等待时它仍然处于活动状态,从而允许主线程在以下情况下接收通知: t 完成,导致主线程缩短其等待时间。
| 归档时间: |
|
| 查看次数: |
1168 次 |
| 最近记录: |