绝对B在这里是正确的。请参阅IllegalMonitorStateException的 API 文档:
抛出以指示线程已尝试在对象的监视器上等待,或通知其他线程在对象的监视器上等待而不拥有指定的监视器。
获取的监视器是当前线程(顺便说一下,API 文档警告不要这样做)。wait 和 notify 方法在 obj 上调用,它们应该在当前线程对象上调用。
A. Object#wait 可以抛出 InterruptedException。是否发生这种情况取决于实现,语言规范说:
设线程 t 为对对象 m 执行等待方法的线程,设 n 为 t 对 m 的未与解锁动作匹配的锁定动作的数量。发生以下操作之一:
如果 n 为零(即线程 t 尚未拥有目标 m 的锁),则抛出 IllegalMonitorStateException。
如果这是一个定时等待且 nanosecs 参数不在 0-999999 范围内或 millisecs 参数为负数,则抛出 IllegalArgumentException。
如果线程 t 被中断,则抛出 InterruptedException 并将 t 的中断状态设置为 false。
否则,将发生以下顺序:(...)
所以没有严格定义首先检查哪些情况。实际上,Oracle 或 IBM JDK 中不会抛出 InterruptedException,而 IllegalMonitorStateException 会。
但是这段代码本身不会导致InterruptedException,需要在线程上调用中断。我用来尝试的代码是:
public class Test implements Runnable {
public void run() {
Object obj = new Object();
Thread.currentThread().interrupt();
try {
synchronized(Thread.currentThread()) {
obj.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new Thread(new Test()).start();
}
}
所以理论上A可能是正确的。认证测试问题需要相当明确,规范对这一点有点模棱两可让我认为这不是一个很好的测试问题。
C. “TimeoutException”是假的。如果传入超时的等待过期,则该方法正常返回。
D. 颠倒等待和通知调用的顺序无关紧要,它们都有相同的要求。
E. 另一个线程所做的任何事情都不能使该线程正常完成,因为它被写入。
F.方法wait在Object上,不是Thread,不需要强制转换。
鉴于 B 绝对正确,并且它描述了 Java 程序员需要理解的一个重要点,而 A 是基于对规范的模糊争论,如果你只能选择一个答案,我会推荐 B。