我使用Java Concurrent API进行任务提交:
Future<Integer> processFuture = taskExecutor.submit(callable);
try {
result = processFuture.get(this.executionTimeout, TimeUnit.SECONDS).intValue();
}
catch (TimeoutException e) {
// How to kill the thread here?
throw new ExecutionTimeoutException("Execution timed out (max " + this.executionTimeout / 60 + "min)");
}
catch (...) {
... exception handling for other cases
}
Future#cancel()
方法只会中断线程,但不会终止它。因此我使用了以下技巧:
class DestroyableCallable implements Callable<Integer> {
private Thread workerThread;
@Override
public Integer call() {
workerThread = Thread.currentThread();
return Integer.valueOf(JniBridge.process(...));
}
public void stopWorkerThread() {
if (workerThread != null) {
workerThread.stop();
}
}
}
DestroyableCallable callable = new DestroyableCallable();
Future<Integer> processFuture = taskExecutor.submit(callable);
try {
result = processFuture.get(this.executionTimeout, TimeUnit.SECONDS).intValue();
}
catch (TimeoutException e) {
processFuture.cancel(true);
// Dirty:
callable.stopWorkerThread();
ThreadPoolTaskExecutor threadPoolTaskExecutor = (ThreadPoolTaskExecutor) taskExecutor;
logger.debug("poolSize: " + threadPoolTaskExecutor.getPoolSize() + ", maxPoolSize:"
+ threadPoolTaskExecutor.getMaxPoolSize() + ", activeCount:"
+ threadPoolTaskExecutor.getActiveCount());
}
throw new ...;
}
catch (...) {
... exception handling for other cases
}
此代码存在的问题/疑问:
- 这样做的方法是否正确?还有其他更优雅的替代方案吗?
- 任务执行器上的
activeCount
没有减少,因此任务执行器仍然“认为”线程正在运行。 - 我不得不在
stopWorkerThread()
方法中添加workerThread != null
检查,因为这个变量在某些情况下是null
。我不明白这些情况是什么...
注:
- 本地代码不消耗文件描述符(套接字)。所有内容都作为数据块传递给它,并以同样的方式返回。
- 本地代码需要大量CPU资源。即使它保证会终止,也可能需要很长时间。
赏金编辑:重新审视本地代码的方法/建议已经清晰,请不要在回复中提供此类建议。我需要纯Java解决方案/解决方法。
ThreadPoolTaskExecutor
线程已经真正死亡?我已经查看了代码:它应该真正捕获这种情况。 - dma_k