java 清除 Thread.interrupt() 标志的方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10401947/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Methods that Clear the Thread.interrupt() flag
提问by OverflowingStack
I have recently inherited a large Java Application that has almost no Thread safety in it. What I'm currently working on is getting all of the Threads to correctly handle being interrupted instead of using the very bad Thread.stop()
.
我最近继承了一个几乎没有线程安全的大型 Java 应用程序。我目前正在做的是让所有线程正确处理被中断的情况,而不是使用非常糟糕的Thread.stop()
.
Part of the problem has been that I do not know every method call out there that clears the interrupt flag.
部分问题是我不知道清除中断标志的每个方法调用。
Currently I know that the following will clear the interrupt flag:
目前我知道以下将清除中断标志:
Thread.interrupted()
Thread.sleep(long)
Thread.join()
Thread.join(long)
Object.wait()
Object.wait(long)
What else am I missing? Thank you
我还缺少什么?谢谢
回答by Gray
Part of the problem has been that I do not know every method call out there that clears the interrupt flag.
部分问题是我不知道清除中断标志的每个方法调用。
It is important to clarify that the following methods clear the interrupt flag by just calling them:
需要澄清的是,以下方法只需调用即可清除中断标志:
Thread.interrupted()
Thread.isInterrupted(true) -- added to your list
For this reason Thread.currentThread().isInterrupted()
should always be used instead.
出于这个原因,Thread.currentThread().isInterrupted()
应该始终使用它。
The following methods will clear the interrupted flag by immediatelythrowing InterruptedException
either if they were called and then the thread was interrupted orif the thread was alreadyinterrupted and then they were called (see junit code below). So it is not the method that clears the flag, throwing the exception does.
以下方法将通过立即抛出InterruptedException
来清除中断标志,如果它们被调用然后线程被中断,或者如果线程已经被中断然后它们被调用(参见下面的 junit 代码)。所以不是清除标志的方法,而是抛出异常。
Your initial list:
您的初始清单:
Thread.interrupted()
Thread.sleep(long)
Thread.join()
Thread.join(long)
Object.wait()
Object.wait(long)
Added to your list:
添加到您的列表中:
Thread.sleep(long, int)
Thread.join(int, long)
Thread.isInterrupted(true)
Object.wait(int, long)
BlockingQueue.put(...)
BlockingQueue.offer(...)
BlockingQueue.take(...)
BlockingQueue.poll(...)
Future.get(...)
Process.waitFor()
ExecutorService.invokeAll(...)
ExecutorService.invokeAny(...)
ExecutorService.awaitTermination(...)
CompletionService.poll(...)
CompletionService.take(...)
CountDownLatch.await(...)
CyclicBarrier.await(...)
Semaphore.acquire(...)
Semaphore.tryAcquire(...)
Lock.lockInteruptibly()
Lock.tryLock(...)
Please notethat the proper pattern with anycode that catches InterruptedException
is to immediately re-interrupt the thread. We do this in case others are relying on the thread.isInterrupted()
method:
请注意,捕获任何代码的正确模式InterruptedException
是立即重新中断线程。我们这样做是为了防止其他人依赖该thread.isInterrupted()
方法:
try {
...
} catch (InterruptedException e) {
// immediately re-interrupt the thread
Thread.currentThread().interrupt();
// log the exception or [likely] quit the thread
}
JUnit code that demonstrates some of this:
演示其中一些内容的 JUnit 代码:
assertFalse(Thread.currentThread().isInterrupted());
// you can do this from another thread by saying: someThread.interrupt();
Thread.currentThread().interrupt();
// this method does _not_ clear the interrupt flag
assertTrue(Thread.currentThread().isInterrupted());
// but this one _does_ and should probably not be used
assertTrue(Thread.interrupted());
assertFalse(Thread.currentThread().isInterrupted());
Thread.currentThread().interrupt();
assertTrue(Thread.currentThread().isInterrupted());
try {
// this throws immediately because the thread is _already_ interrupted
Thread.sleep(1);
fail("will never get here");
} catch (InterruptedException e) {
// and when the InterruptedException is throw, it clears the interrupt
assertFalse(Thread.currentThread().isInterrupted());
// we should re-interrupt the thread so other code can use interrupt status
Thread.currentThread().interrupt();
}
assertTrue(Thread.currentThread().isInterrupted());
回答by axtavt
Common convention is the following: any method that throws InterruptedException
(+ Thread.interrupted()
) clears the interrupt flag.
常见约定如下:任何抛出InterruptedException
(+ Thread.interrupted()
) 的方法都会清除中断标志。
So, in order to make your threads interruptable you need to find all places where InterruptedException
gets caught without retrowing it or restoring the interrupt flag. Since InterruptedException
is a checked exception it's not hard to do.
因此,为了使您的线程可中断,您需要找到所有InterruptedException
被捕获的地方,而无需回溯或恢复中断标志。由于InterruptedException
是受检异常,因此不难做到。
回答by Ajax
Here's a SUPER FUN EXAMPLE:
这是一个超级有趣的例子:
ch.qos.logback.core.AsyncAppenderBase prior to version 1.1.4 catches and swallows InterruptedException without resetting the flag on the thread.
1.1.4 版本之前的 ch.qos.logback.core.AsyncAppenderBase 捕获并吞下 InterruptedException 而不重置线程上的标志。
So, if you use anything which routes to this logger (like slf4j), it will silently eat your thread interrupt status. 'Cos, I mean, who doesn't check thread interrupt status before and after every possible log operation?
所以,如果你使用任何路由到这个记录器的东西(比如 slf4j),它会默默地吃掉你的线程中断状态。'因为,我的意思是,谁不在每次可能的日志操作之前和之后检查线程中断状态?