Java的wait()方法为何不抛出InterruptedException异常?

4

我有一个对象在线程A上调用wait(),同时另一个对象在线程B上执行一些工作,然后调用线程A的对象的notify()。线程A然后执行一些后处理。

我的问题非常简单:

synchronized(this)
{
    while(!flag)
    {
        try
        {
            wait();
            getLogger().info("No longer waiting");
        }
        catch (InterruptedException ie)
        {
            getLogger().info("Wait threw InterruptedException");
        }
    }
}

在信息提示中,将“Wait threw InterruptedException”更改为“No longer waiting”。
我感到困惑,因为这个(http://download.oracle.com/javase/1.5.0/docs/api/java/lang/Object.html#wait()):
抛出:
InterruptedException - 如果另一个线程在当前线程等待通知时中断了当前线程。当抛出此异常时,当前线程的中断状态被清除。
为什么我会得到奇怪的行为?
谢谢。

另一个线程在您的对象上调用notify并不算作中断。 - sje397
4个回答

10

当一个线程使用 wait() 等待时,他实际上是在等待另一个线程调用 notify()。所以一旦其他线程调用了 notify(),这个线程将继续执行;而如果你调用了 interrupt(),则会抛出异常。

此外,从您提供的文档中可以看到:

导致当前线程等待,直到另一个线程调用此对象的 notify() 方法或 notifyAll() 方法

notify 会释放线程的锁。

如果在当前线程等待通知期间,另一个线程中断了当前线程,则会抛出 InterruptedException 异常。

 


谢谢,我一直以为notify()会导致wait()抛出InterruptedException异常。 - Liam Fledgings

3

notify() 方法并不会让 wait() 方法抛出 InterruptedException 异常。相反,notify() 方法会让 wait() 方法继续正常的程序流程。


2

notify()不是一个对于正在wait()的线程而言的异常终止。如果在notify()被调用之前线程被终止,你会得到异常,而不是由于notify()被调用而产生的结果。该线程并未被中断,而是被唤醒。


0
请注意,您的代码中存在一个错误。wait 应该始终在循环中调用,并在唤醒后检查条件。
wait 可能会被虚假唤醒。请参阅 javadoc wait()

考虑到我们没有看到代码的上下文,你无法确定它是否有一个bug。它也不在同步块中,但我假设在某个地方有一个。 - Jon Skeet
@Jon Skeet。原始帖子中没有带条件的循环,OP说“然后线程A执行一些后处理。”这意味着他想等到另一个线程完成处理。没有检查条件的等待是一个错误,因为会出现虚假唤醒。线程可能会在未收到通知的情况下被唤醒,然后开始执行后处理,而另一个线程尚未完成。 - Kaj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接