我在谷歌上搜索了关于杀死Java线程的解决方案。目前存在两种解决方案:
- 设置一个标志位
- 使用Thread.interrupt
但是这两种方法都不适合我。因为我的线程调用了一个需要很长时间才能完成的第三方API,如果执行时间太长,我想让用户取消该线程。
那么我应该如何结束该线程呢?感谢您的帮助。
我在谷歌上搜索了关于杀死Java线程的解决方案。目前存在两种解决方案:
但是这两种方法都不适合我。因为我的线程调用了一个需要很长时间才能完成的第三方API,如果执行时间太长,我想让用户取消该线程。
那么我应该如何结束该线程呢?感谢您的帮助。
Thread.interrupt()
是通常适用的唯一安全方法。当然,您也可以使用其他应用程序级信号(例如对易失变量的条件检查)来自我终止。其他方法(如所有已弃用的 Thread.xx 方法)可能以不确定的方式污染应用程序状态,并且需要重新加载所有应用程序状态。
理论上,您可以调用被弃用的Thread.stop()
方法。但是请注意,这可能会导致您的应用程序行为出现意外和不可预测的情况...这取决于第三方库实际正在执行什么操作。Thread.stop()
和相关方法基本上是不安全的。
最好的解决方案是修改第三方库以响应Thread.interrupt。如果您无法这样做,则应该放弃它并找到/使用更好的库。
Future.cancel
方法使用 Thread.interrupt()
,而我们已经被告知 Thread.interrupt()
不是一个解决方案。 - Stephen CCallable<DataTypeReturnedBy3rdPartAPI>
中,然后使用SingleThreadExecutor
执行它,并指定一个超时时间。按照这种方法,如果调用第三方API的时间超过timeOut
,线程将被终止。以下是一些代码示例:ExecutorService executor = Executors.newSingleThreadExecutor();
try {
//================= HERE ==================
Future<Boolean> job = executor.submit(thirdPartyCallable);
executor.awaitTermination(timeOut, TimeUnit.SECONDS);
if(!job.isDone())
logger.debug("Long call to 3rd party API didn't finish");
//=========================================
} catch (Exception exc) {
exc.printStackTrace();
} finally {
if(!executor.isShutdown() )
executor.shutdownNow();
}
}
private static Callable<Boolean> thirdParytCallable = new Callable<Boolean>() {
public Boolean call() throws Exception {
//Call to long 3rd party API
//.......
for(long i = 0;i<99999991999999L;i++) {
Thread.sleep(10L);// Emulates long call to 3rd party API
System.out.print(".");
}
return Boolean.valueOf(true);//Data from 3rd party API
}
};
由于Thread.stop()
已被(正确地)弃用,通常可以通过将标志设置为true来实现。类似这样:
调用类:
...
workListExecutor.stop()
...
WorkListExecutor.class:
boolean running = true;
void stop(){
running = false;
}
void run(){
while (running) {
... do my stuff ...
}
}
假设您的线程有某种主循环(通常情况下是这样)。
如果循环中的代码太大,您可以定期检查running
是否仍然为true
,如果不是,则退出。
这样做的好处是在完成时仍然可以清理。当您的运行方法完成时,线程将自动终止。
你可以尝试使用 Thread.stop(),但是要自行承担风险(at your own risk)。最理想的情况是,你调用的API应该有一种中断操作的方式(如果API本身没有提供更干净的中断进度的方法,你尝试过 Thread.interrupt() 吗?)。
您可以在Thread对象上调用stop
方法,但强烈建议不要这样做。请阅读:http://download.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html
您是否有自由对API进行小的更改?此阻塞调用是CPU绑定还是IO绑定?如果它是IO绑定的,并且您可以访问底层套接字/远程通信对象,则关闭该对象可能会产生奇效。这至少比停止线程要好。