【发布时间】:2012-02-04 10:32:31
【问题描述】:
在我的应用程序中,我有一个通过 JNI 桥调用的本机代码的包装器。此本机代码需要在单独的线程中执行(并行处理)。但是问题是代码有时会“挂起”,因此需要“强制”终止线程。不幸的是,我还没有找到任何“微妙”的方法来做到这一点:一般建议是告诉线程中的代码优雅地退出,但我不能用这个本机代码(上面都是第 3 方代码)来做到这一点。
我使用 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没有减少,因此任务执行器仍然“认为”线程正在运行 - 我不得不将
workerThread != nullcheck 添加到stopWorkerThread()方法中,因为在某些情况下这个变量是null。我不明白这些情况是什么......
注意事项:
- 本机代码不使用文件描述符(套接字)。一切都作为数据块传递给它,并以相同的方式返回。
- 本机代码占用大量 CPU。即使它保证终止,也可能需要很长时间。
赏金编辑:重新访问本机代码的方法/建议很明确,请不要在回复中提供。我需要纯 Java 解决方案/解决方法。
【问题讨论】:
标签: java multithreading