据我所知,这是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()
?
答案 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
}
}
如果您不知道如何使用该方法,那么良好的方式建议您应该重新中断该线程。