5

我想管理我的 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<String> 并检查 Thread.interrupted() 状态的任务

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

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

我正在构建 java 1.6.0_02-b05

4

3 回答 3

6

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

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

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

于 2010-01-21T13:52:45.983 回答
2

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

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

于 2010-01-21T13:45:13.360 回答
2

至少,您应该恢复中断标志以使 taskExecutor 知道线程中断:

public String call() { 
    while (true) { 
        if (Thread.interrupted()) { 
            Thread.currentThread().interrupt();
            break; 
        } 
        doSomething(); 
    } 
} 
于 2010-01-21T12:59:20.733 回答