运行 Java 中 main() 中的线程实例上的 wait()
Running wait() on a Thread instance from within main() in Java
我在 java.lang.Object 中使用定时版本的 wait() 并观察到它在两种不同情况下的行为不同。
场景1:在Thread
中使用运行()的默认定义
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");
}
关于场景 1 的问题: 我遇到 X 和 Y 之间的延迟。这是因为我正在从 main 调用 wait() (即使在 t 上),因此正在使用主线程的调用堆栈,而不是第二个线程的调用堆栈?
场景 2: 即时子类化线程以覆盖 运行() 以打印某些内容。
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");
}
关于场景 2 的问题: 我没有遇到任何延迟!仅仅因为我覆盖了 运行() 就发生了什么变化?现在,每次我 运行 程序时,它都会立即打印 "XI am the second thread.Y",没有任何延迟! wait()的效果去哪儿了?
您实际上已经 运行 了解为什么您永远不应该在 Thread 上调用 wait
或 notify(All)
(请参阅 Thread 的 JavaDocs)。在内部,Thread 使用 wait 和 notifyAll 来实现 Thread.join(),所以在第二种情况下发生的是你的线程进入等待,但随后另一个线程死掉并调用 notifyAll(),这唤醒了你的主线程。
如果你只想等待一个经过的时间,使用Thread.sleep
,如果你真的想等待线程的终止,使用Thread.join
。此外,请阅读 Object
中的 javadoc,以正确使用 wait
、notify
和 notifyAll
。
public final void join(long millis)
throws InterruptedException
Waits at most millis milliseconds for this thread to die. A timeout of
0 means to wait forever. This implementation uses a loop of this.wait
calls conditioned on this.isAlive. As a thread terminates the
this.notifyAll method is invoked. It is recommended that applications
not use wait, notify, or notifyAll on Thread instances.
相关且正确,我 +1。我将尝试添加一些信息,说明为什么这是相关的。
当你打电话时
synchronized(t) { t.wait(10000);}
在主线程中,是主线程在做等待。 t
是主线程正在等待的监视器。您期望这会使您的 t
线程进入休眠状态是错误的。
这里的monitor(被锁定的共享对象,刚好是t
)用于不同线程之间的通信,一个线程在monitor上调用notifyAll,其他线程在monitor上等待收到通知。您可以将监视器视为共享通信点。
在您的第一个示例中,线程 t 立即启动并结束(因为它没有任何事情要做)。线程在主线程开始等待之前完成并发送通知,因此您会看到等待超时之前的延迟。
在第二个例子中,线程 t 有东西要打印,它和主线程之间存在竞争条件。这是一场混战,先发生什么取决于时间的偶然性。你看到的是线程 t
现在必须向控制台打印一行,所以它设法保持忙碌足够长的时间,以至于在主线程开始等待时它仍然存在,允许主线程在 t 完成时接收通知,导致主线程缩短等待时间。
我在 java.lang.Object 中使用定时版本的 wait() 并观察到它在两种不同情况下的行为不同。
场景1:在Thread
中使用运行()的默认定义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");
}
关于场景 1 的问题: 我遇到 X 和 Y 之间的延迟。这是因为我正在从 main 调用 wait() (即使在 t 上),因此正在使用主线程的调用堆栈,而不是第二个线程的调用堆栈?
场景 2: 即时子类化线程以覆盖 运行() 以打印某些内容。
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");
}
关于场景 2 的问题: 我没有遇到任何延迟!仅仅因为我覆盖了 运行() 就发生了什么变化?现在,每次我 运行 程序时,它都会立即打印 "XI am the second thread.Y",没有任何延迟! wait()的效果去哪儿了?
您实际上已经 运行 了解为什么您永远不应该在 Thread 上调用 wait
或 notify(All)
(请参阅 Thread 的 JavaDocs)。在内部,Thread 使用 wait 和 notifyAll 来实现 Thread.join(),所以在第二种情况下发生的是你的线程进入等待,但随后另一个线程死掉并调用 notifyAll(),这唤醒了你的主线程。
如果你只想等待一个经过的时间,使用Thread.sleep
,如果你真的想等待线程的终止,使用Thread.join
。此外,请阅读 Object
中的 javadoc,以正确使用 wait
、notify
和 notifyAll
。
public final void join(long millis) throws InterruptedException
Waits at most millis milliseconds for this thread to die. A timeout of 0 means to wait forever. This implementation uses a loop of this.wait calls conditioned on this.isAlive. As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.
当你打电话时
synchronized(t) { t.wait(10000);}
在主线程中,是主线程在做等待。 t
是主线程正在等待的监视器。您期望这会使您的 t
线程进入休眠状态是错误的。
这里的monitor(被锁定的共享对象,刚好是t
)用于不同线程之间的通信,一个线程在monitor上调用notifyAll,其他线程在monitor上等待收到通知。您可以将监视器视为共享通信点。
在您的第一个示例中,线程 t 立即启动并结束(因为它没有任何事情要做)。线程在主线程开始等待之前完成并发送通知,因此您会看到等待超时之前的延迟。
在第二个例子中,线程 t 有东西要打印,它和主线程之间存在竞争条件。这是一场混战,先发生什么取决于时间的偶然性。你看到的是线程 t
现在必须向控制台打印一行,所以它设法保持忙碌足够长的时间,以至于在主线程开始等待时它仍然存在,允许主线程在 t 完成时接收通知,导致主线程缩短等待时间。