dma*_*a_k 7 java multithreading
在我的应用程序中,我有一些本机代码的包装器,它通过JNI桥调用.此本机代码需要在单独的线程中执行(并行处理).但问题是代码有时会"挂起",因此线程需要"强制"终止.不幸的是我没有找到任何"微妙"的方法:一般建议是告诉线程中的代码优雅地退出,但我不能用这个本机代码(这是上面的第三方代码).
我使用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
}
Run Code Online (Sandbox Code Playgroud)
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
}
Run Code Online (Sandbox Code Playgroud)
这段代码的问题/问题:
activeCount
任务执行程序没有减少,因此任务执行程序仍然"认为"该线程正在运行workerThread != null
check to stopWorkerThread()
方法,因为这个变量null
在某些情况下变成了.我无法理解这些案件是什么......笔记:
赏金编辑:重新访问本机代码的方法/建议很明确,请不要在回复中提供.我需要纯Java解决方案/解决方法.
Java具有强制线程终止的纯选项.它是古老的,不推荐使用Thread.stop()(AFAIK).并且没有安全线程终止的选项(为什么.stop()被弃用,并且甚至不允许JVM实现者实现).
原因是应用程序内的所有线程共享内存和资源 - 因此,如果您在某个任意点强制终止线程,则无法确定终止线程未将某些共享内存/资源置于不一致状态.你甚至不能(通常)假设哪些资源(可能)是脏的('因为你不知道线程被停止的确切位置).
因此,如果您希望应用程序的某些线程能够中断,唯一的解决方案是在设计阶段提供"保存点"的一些表示法 - 目标线程代码中的位置,保证不会改变共享因此,线程退出此处是安全的.而且正是Thread.stop()javadocs告诉你的:安全地中断线程的唯一方法是设计线程的代码,这样它就可以自己响应某种中断请求.某种标志,由线程不时检查.
我试图告诉你:你不能做你被问及使用java线程/并发的事情.我建议你的方式(这是早在这里给出的)是在不同的过程中完成你的工作.强制终止进程比线程安全得多,因为1)进程彼此分离得多,2)OS在进程终止后负责许多清理.杀戮过程并不是完全安全的,因为存在某种资源(例如文件),默认情况下不会被操作系统清除,但在您的情况下它似乎是安全的.
所以你设计了一个小的独立应用程序(甚至可能在java中 - 如果你的第三方库没有提供其他绑定,甚至在shell脚本中),只有工作是让你计算.你从主应用程序开始这样的过程,给它工作,并启动看门狗.它看门狗检测到超时 - 它强行杀死进程.
这是唯一的解决方案草案.你可以实现某种进程池,如果你想提高性能(启动过程可能需要时间),等等......
归档时间: |
|
查看次数: |
7034 次 |
最近记录: |