Java Thread - 奇怪的 Thread.interrupted() 和 future.cancel(true) 行为
我想管理我的 TaskExecutor 返回的 Futures 对象列表。
我有这样的
List<Future<String>> list
void process(ProcessThis processThis) {
for ( ...) {
Future<String> future = taskExecutor.submit(processThis);
list.add(future)
}
}
void removeFutures() {
for(Future future : list) {
assert future.cancel(true);
}
ProcessThis 是一个实现 Callable< 的任务字符串>并检查 Thread.interrupted() 状态
public String call() {
while (true) {
if (Thread.interrupted()) {
break;
}
doSomething();
}
}
现在的问题是,当调用 Thread.interrupted() 时,只有一部分并发线程返回“true”。
对于每个被删除的 future,removeFutures() 中的断言都会返回 true(我还检查了 isDone() 和 isCompleted()。
被中断的线程数量是随机的。超过 15 个正在运行的线程,有时 13 个被中断,有时 2 个...
我实在不明白问题出在哪里。如果我调用 future.cancel(true) 并且返回 true...然后我检查 Thread.interrupted (仅调用一次),我希望它也返回 true。
知道我错过了什么吗?
我正在构建 java 1.6.0_02-b05
I want to manage a list of Futures objects returned by my TaskExecutor.
I've something like this
List<Future<String>> list
void process(ProcessThis processThis) {
for ( ...) {
Future<String> future = taskExecutor.submit(processThis);
list.add(future)
}
}
void removeFutures() {
for(Future future : list) {
assert future.cancel(true);
}
ProcessThis is a task that implements Callable< String> and checks for Thread.interrupted() status
public String call() {
while (true) {
if (Thread.interrupted()) {
break;
}
doSomething();
}
}
Now the problem is that only a subset of the concurrent Threads is returning 'true' when Thread.interrupted() is called.
The assert in removeFutures() returns true for every future that is removed (I checked isDone() and isCompleted() as well.
The number of Threads that are interrupted is random. Over 15 running Threads sometimes 13 are interrupted, sometimes 2 ...
I really don't understand where's the issue. if I call future.cancel(true) and this returns true... and then I check Thread.interrupted (this is called only once), I expect this to return true as well.
Any idea of what am I missing?
I'm on build java 1.6.0_02-b05
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
请注意,
Thread.interrupted()
返回当前中断状态,然后将其清除,因此所有将来的调用都将返回 false。您想要的可能是 Thread.currentThread().isInterrupted() 。另请注意,如果任务已完成或取消,
future.cancel(true)
通常只会返回 false。如果它返回 true,则不能保证任务实际上会被取消。doSomething()
中发生了什么?由于中断,RuntimeException 可能会在某个地方逃逸。您是否有 UncaughtExceptionHandler 设置?如果没有,您需要传递 ThreadFactory 到Executor
,它将设置异常处理程序并记录任何错过的异常。Be aware that
Thread.interrupted()
returns the current interrupted status and then clears it, so all future invocations will return false. What you want is probablyThread.currentThread().isInterrupted()
.Also be aware that
future.cancel(true)
will usually only return false if the task had already been completed or canceled. If it returns true, that is no guarantee that the task will actually be canceled.What is happening in
doSomething()
? Its possible that a RuntimeException is escaping somewhere due to the interrupt. Do you have an UncaughtExceptionHandler set? If not, you'll need to pass a ThreadFactory to theExecutor
that will set the exception handler and log any missed exceptions.至少,你应该恢复中断标志以使taskExecutor知道线程中断:
At least, you should restore the interruption flag to make taskExecutor aware of the thread interruption:
一个潜在的问题是中断经常被吞掉。因此,在 doSomething() 深处(甚至在类加载中),中断可能会被例如 wait() 捕获,然后被“粗心”的代码丢弃。在我看来,中断是邪恶的。
可能值得检查所有任务在取消时是否实际上正在运行。
A potential problem that interrupts are often swallowed. So somewhere deep in
doSomething()
(or even in class loading), an interrupt may be caught by, say,wait()
and then discarded by 'careless' code. Interrupts are evil, IMO.It may be worth checking that all of you tasks are actually running at the time of the cancel.