Java线程 - 奇怪的Thread.interrupted()和future.cancel(true)行为

时间:2010-01-21 12:56:02

标签: java multithreading threadpool interrupt future

我想管理由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&lt;的任务。串GT;并检查Thread.interrupted()状态

    public String call() {
        while (true) {
            if (Thread.interrupted()) {
                break;
            }
            doSomething();
        }
    }

现在的问题是,当调用Thread.interrupted()时,只有并发线程的子集返回'true'。
removeFutures()中的断言为每个被删除的未来返回true(我也检查了isDone()和isCompleted()。
被中断的线程数是随机的。超过15个运行的线程有时13个被中断,有时2 ...
我真的不明白问题出在哪里。如果我调用future.cancel(true)并返回true ...然后我检查Thread.interrupted(这只被调用一次),我希望这也会返回true。
知道我错过了什么吗?

我正在构建java 1.6.0_02-b05

3 个答案:

答案 0 :(得分:6)

请注意,Thread.interrupted()会返回当前中断状态,然后将其清除,因此以后所有调用都将返回false。你想要的可能是Thread.currentThread().isInterrupted()

另请注意,如果任务已经完成或取消,future.cancel(true)通常只会返回false。如果它返回true,则不能保证任务实际上将被取消。

doSomething()发生了什么?由于中断,RuntimeException可能会在某处转义。你有UncaughtExceptionHandler套吗?如果没有,您需要将ThreadFactory传递给Executor,{{1}}将设置异常处理程序并记录任何错过的异常。

答案 1 :(得分:2)

至少,您应该恢复中断标志,以使taskExecutor意识到线程中断:

public String call() { 
    while (true) { 
        if (Thread.interrupted()) { 
            Thread.currentThread().interrupt();
            break; 
        } 
        doSomething(); 
    } 
} 

答案 2 :(得分:2)

经常吞下中断的潜在问题。因此,在doSomething()深处(甚至在类加载中)的某个地方,中断可能会被wait()捕获,然后被'粗心'代码丢弃。中断是邪恶的,IMO。

可能值得检查所有任务是否在取消时实际运行。