例如:
public synchronized Object get() {
while (result == null) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
// Do we own the monitor of this object?
}
}
return result;
}
当e.printStackTrace()
执行时,我们是否保证拥有对象的监视器?
该引用表示当wait()
或notify()
调用后notifyAll()
返回时,该线程会等待它获取对象的监视器。但是当wait()
抛出异常时呢?
答案 0 :(得分:6)
等待返回时(包括抛出InterruptedException的情况),线程必须有监视器,否则它不能在该synchronized方法中执行。线程必须先获取监视器才能离开wait方法。然后,一旦它离开wait方法,线程就有了监视器,并在线程离开方法时释放它。
这里最好将InterruptedException抛给调用者而不是吃掉它。你的目标是快速离开,让调用者知道发生了中断,这样就可以解决问题。在这里吃它也似乎意味着你再次回到while循环。 java.util.concurrent使用中断来实现取消,特别是如果你使用java.util.concurrent工具,编写与它们兼容的代码是有意义的。
答案 1 :(得分:4)
是。实际上,重新获取监视器后会抛出此InterruptedException
。
请参阅wait in jls:
让线程t成为对象m上执行wait方法的线程,并且 设n是m上没有的t的锁定动作的数量 与解锁操作相匹配。发生以下操作之一:
如果n为零(即,线程t还没有锁定 target m),然后抛出IllegalMonitorStateException。
如果这是一个定时等待并且nanosecs参数不在范围内 0-999999或毫秒参数是负数,然后是 抛出IllegalArgumentException。
如果线程t被中断,则抛出InterruptedException t的中断状态设置为false。
否则,将发生以下序列:
- 的行动
将线程t添加到对象m的等待集中,并执行n unlock m。
线程t在执行之前不会执行任何进一步的指令 从m的等待集中删除。可以从等待集中删除该线程 由于以下任何一种行为,并将在某个时间恢复 之后:
对m执行通知操作,其中选择了t 从等待集中删除。
- 执行的notifyAll操作
正在对m。
正在执行中断操作。
如果这是一次定时等待,则会从m等待中删除内部操作 设置在至少毫秒毫秒加上纳秒之后发生 自等待操作开始以来经过了纳秒。
实施的内部行动。实施是 允许,尽管不鼓励,进行“虚假的唤醒”, 也就是说,从等待集中删除线程,从而启用恢复 没有明确的指示。
主题t对m执行n次锁定操作。
如果由于a而在步骤2中从m的等待集中删除了线程t 中断,然后将t的中断状态设置为false并等待 抛出InterruptedException。