在哪里使用synchronized块捕获Object.wait()的InterruptedException?

时间:2013-01-09 12:00:37

标签: java multithreading notify interrupted-exception

据我所知,这是Java中多线程的非常常见的片段。

boolean loaded = false;
Object lock = new Object();

public void block() {
    synchronized (lock) {
        while(!loaded)
            lock.wait(); // Unhandled exception type InterruptedException
    }
}

并在另一个帖子中

public void done () {
    synchronized (lock) {
        loaded = true;
        lock.notify();
    }
}

但我不确定我应该把它放在哪里,我可以围绕整个同步块或仅lock.wait()?什么是经验法则,它真的重要吗?

处理是否可以在这种情况下拨打Thread.currentThread().interrupt()

2 个答案:

答案 0 :(得分:6)

您可能需要考虑Brian Goetz撰写的文章:Java theory and practice: Dealing with InterruptedException

通常,如果您不知道该怎么做,那么除了让调用者代码知道在等待锁定时可以中断此方法时,不要做任何事情。您可以通过将 throws InterruptedException 添加到方法签名来完成此操作。

如果由于某种原因你被迫添加一个try / catch块并处理异常,那么 Thread.currentThread()。interrupt()会做但重新抛出它可以是合适的。

答案 1 :(得分:3)

  

但我不确定我应该把try和catch放在哪里,我可以包围整个同步块或只有lock.wait()?什么是经验法则,它真的重要吗?

lock.wait()是唯一可以在block方法中引发异常的行。因此,无论是将try / catch放在等待还是包含整个方法体都没有区别于执行的角度(假设你在两种情况下都退出循环 - 如果你想继续循环那么try / catch块显然应该在循环内。)

换句话说,这只是一种风格问题 - 见this other discussion。我个人认为这更具可读性:

try {
    synchronized (lock) {
        while (!loaded) {
            lock.wait(); // Unhandled exception type InterruptedException
        }
    }
} catch (InterruptedException e) {
    //to ignore me or not to ignore me, that is the question
    Thread.currentThread().interrupt();
}
  

处理是否可以在这种情况下调用Thread.currentThread()。interrupt()?

在下面的第一个例子中,可以捕获InterruptedException并在不重新中断线程的情况下退出循环,因为在任何情况下run方法都将退出并且线程将死掉:

new Thread(new Runnable() {

    @Override
    public void run() {
        block();
    }
}).start();

在下面的第二个例子中,你当然应该重新中断线程,让run方法知道block()退出的原因是加载变为true还是被中断:

public void run() {
    while(!Thread.currentThread().isInterrupted()) {
        loaded = false;
        System.out.println("Launching data load");
        block(); //if false has become true, loop, if interrupted, exit
    }
}

如果您不知道如何使用该方法,那么良好的方式建议您应该重新中断该线程。