我正在使用CountDownLatch在两个线程之间同步初始化过程,我想知道它可能引发的InterruptedException的正确处理。
我最初编写的代码是这样的:
private CountDownLatch initWaitHandle = new CountDownLatch(1);
/**
* This method will block until the thread has fully initialized, this should only be called from different threads Ensure that the thread has started before this is called.
*/
public void ensureInitialized()
{
assert this.isAlive() : "The thread should be started before calling this method.";
assert Thread.currentThread() != this, "This should be called from a different thread (potential deadlock)";
while(true)
{
try
{
//we wait until the updater thread initializes the cache
//that way we know
initWaitHandle.await();
break;//if we get here the latch is zero and we are done
}
catch (InterruptedException e)
{
LOG.warn("Thread interrupted", e);
}
}
}
这种模式有意义吗?基本上,忽略InterruptedException是一个好主意,只要一直等待它成功即可。我想我只是不了解这种情况会被打断的情况,所以我不知道我是否应该以不同的方式处理它们。
为什么会在这里引发InterruptedException,最佳的处理方式是什么?
这恰恰是您不应该做的InterruptedException
。从InterruptedException
本质上来说,An
是对该线程终止的礼貌请求。该线程应清理并尽快退出。
IBM对此发表了一篇很好的文章:http
:
//www.ibm.com/developerworks/java/library/j-jtp05236.html
这是我会做的:
// Run while not interrupted.
while(!(Thread.interrupted())
{
try
{
// Do whatever here.
}
catch(InterruptedException e)
{
// This will cause the current thread's interrupt flag to be set.
Thread.currentThread().interrupt();
}
}
// Perform cleanup and exit thread.
这样,这样做的好处是:如果在阻塞方法中线程被中断,则不会设置中断位,InterruptedException
而是抛出an
。如果您的线程在没有阻塞方法的情况下被中断,则将设置被中断的位,并且不会引发异常。因此,通过调用interrupt()
在异常上设置标志,两种情况都被规范化为第一种情况,然后由循环条件检查。
另外,这还使您可以通过简单地中断线程来停止线程,而无需发明自己的机制或接口来设置一些布尔标志来执行完全相同的操作。