Java OCJP转储线程同步方法

Java OCJP转储线程同步方法,java,multithreading,scjp,java-threads,Java,Multithreading,Scjp,Java Threads,嗨,我正在处理SCJP转储,但现在我遇到了一个问题。问题是: void waitForSignal(){ Object obj = new Object(); synchronized(Thread.currentThread()){ obj.wait(); obj.notify(); } } 哪种说法是正确的 A.此代码可能引发InterruptedException B.此代码可能引发非法MonitorStateException C.此代码可

嗨,我正在处理SCJP转储,但现在我遇到了一个问题。问题是:

void waitForSignal(){
   Object obj = new Object();
   synchronized(Thread.currentThread()){
       obj.wait();
       obj.notify();
   }
}
哪种说法是正确的

A.此代码可能引发InterruptedException

B.此代码可能引发非法MonitorStateException

C.此代码可以在十分钟后引发TimeoutException

D.颠倒obj.wait()和obj.notify()的顺序可能会导致此方法正常完成

E.从另一个线程调用notify()或notifyAll()可能会导致此方法正常完成

除非将“obj.wait()”替换为“((线程)obj.wait()”,否则此代码不会编译


我发现在一个转储文件中答案是A,而在另一个转储文件中答案是B。有人能得到正确的答案并为我提供解释吗?

这里B肯定是正确的。有关以下内容,请参阅API文档:

抛出以指示线程试图在对象的监视器上等待,或通知在不拥有指定监视器的情况下在对象监视器上等待的其他线程

获取的监视器是当前线程(顺便说一下,API文档警告不要这样做)。方法wait和notify在obj上被调用,它们应该在当前线程对象上被调用

A.对象#wait可以抛出InterruptedException。是否发生这种情况取决于实施情况,报告说:

假设线程t是在对象m上执行wait方法的线程,n是t在对象m上执行的未与解锁操作匹配的锁定操作数。发生以下操作之一:

  • 如果n为零(即线程t尚未拥有目标m的锁),则会抛出一个IllegalMonitorStateException

  • 如果这是一次定时等待,且nanosecs参数不在0-999999的范围内,或者毫秒参数为负,则会引发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在理论上可能是正确的。认证测试问题需要合理明确,规范对此有点含糊不清,这让我觉得这不是一个好的测试问题

“TimeoutException”是假的。如果传入超时的等待过期,该方法将正常返回

D.颠倒等待和通知呼叫的顺序并不重要,它们都有相同的要求

其他线程所做的任何事情都不能使该线程在写入时正常完成

F.方法wait在对象上,而不是线程上,不需要强制转换


考虑到B是绝对正确的,它描述了Java程序员需要理解的一个重要点,而A是基于关于规范的含糊不清的诡辩,如果你只能选择一个答案,我推荐B。

这里B肯定是正确的。有关以下内容,请参阅API文档:

抛出以指示线程试图在对象的监视器上等待,或通知在不拥有指定监视器的情况下在对象监视器上等待的其他线程

获取的监视器是当前线程(顺便说一下,API文档警告不要这样做)。方法wait和notify在obj上被调用,它们应该在当前线程对象上被调用

A.对象#wait可以抛出InterruptedException。是否发生这种情况取决于实施情况,报告说:

假设线程t是在对象m上执行wait方法的线程,n是t在对象m上执行的未与解锁操作匹配的锁定操作数。发生以下操作之一:

  • 如果n为零(即线程t尚未拥有目标m的锁),则会抛出一个IllegalMonitorStateException

  • 如果这是一次定时等待,且nanosecs参数不在0-999999的范围内,或者毫秒参数为负,则会引发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在理论上可能是正确的。认证测试问题需要合理明确,规范对此有点含糊不清,这让我觉得这不是一个好的测试问题

“TimeoutException”是假的。如果传入超时的等待过期,该方法将正常返回

D.颠倒等待和通知呼叫的顺序并不重要,它们都有相同的要求

其他线程所做的任何事情都不能使该线程在写入时正常完成

F.方法wait在对象上,而不是线程上,不需要强制转换

考虑到B是绝对正确的,并且它描述了Java程序员需要理解的一个重要点,而A是基于关于规范的模糊的诡辩,如果您只能选择一个答案,我推荐B