6

据我了解,这是 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();
    }
}

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

Thread.currentThread().interrupt()在这种情况下可以打电话来处理吗?

4

2 回答 2

6

您可能需要考虑 Brian Goetz 的文章:Java 理论与实践:处理 InterruptedException

一般来说,如果你不知道该做什么,那么什么都不做,只让调用者代码知道这个方法可以在等待锁时被中断。您可以通过将throws InterruptedException添加到方法签名来做到这一点。

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

于 2013-01-09T12:09:27.977 回答
3

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

lock.wait()block是唯一可以在您的方法中引发异常的行。因此,无论您是在等待中放置 try/catch 还是包含整个方法主体,从执行的角度来看都不会产生影响(当然,假设您在两种情况下都退出循环 - 如果您想继续循环,那么 try/catch 块显然应该在循环内)。

换句话说,这只是一个风格问题 - 请参阅其他讨论。我个人认为这更具可读性:

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()退出的原因是加载变为真还是被中断:

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
    }
}

如果您不知道该方法将如何使用,礼貌建议您应该重新中断线程。

于 2013-01-09T12:54:05.220 回答