Java 如何中断给定未来对象的线程?
我想启动一个线程,如果它没有在5秒内完成,则取消它:Java 如何中断给定未来对象的线程?,java,multithreading,threadpool,executorservice,futuretask,Java,Multithreading,Threadpool,Executorservice,Futuretask,我想启动一个线程,如果它没有在5秒内完成,则取消它: private final class HelloWorker implements Callable<String> { public String call() throws Exception { while(true) { if (Thread.isInterrupted()) { return null; }
private final class HelloWorker implements Callable<String> {
public String call() throws Exception {
while(true) {
if (Thread.isInterrupted()) {
return null;
}
}
return performExpensiveComputation();
}
private String performExpensiveComputation() {
// some blocking expensive computation that may or may not take a very long time
}
}
private ExecutorService executorService = Executors.newFixedThreadPool(threadPoolSize);
Future<String> future = executorService.submit(new HelloWorker());
try {
String s = future.get(5, TimeUnit.SECONDS);
} catch (TimeoutException e) {
future.cancel(true);
System.out.println("cancelled: " + future.isCancelled() + "done: " + future.isDone());
executorService.shutdown();
try {
System.out.println("try to terminate: " + executorService.awaitTermination(60, TimeUnit.SECONDS));
} catch (Exception ex) {
// ignore
}
}
private final类HelloWorker实现了可调用{
公共字符串调用()引发异常{
while(true){
if(Thread.isInterrupted()){
返回null;
}
}
返回performExpensiveComputation();
}
专用字符串performExpensiveComputation(){
//一些阻塞可能需要或不需要很长时间的昂贵计算
}
}
私有ExecutorService ExecutorService=Executors.newFixedThreadPool(threadPoolSize);
Future=executorService.submit(新HelloWorker());
试试{
字符串s=future.get(5,TimeUnit.SECONDS);
}捕获(超时异常e){
future.cancel(true);
System.out.println(“取消:”+future.isCancelled()+“完成:”+future.isDone());
executorService.shutdown();
试一试{
System.out.println(“尝试终止:”+executorService.waittermination(60,TimeUnit.SECONDS));
}捕获(例外情况除外){
//忽略
}
}
然而,它看起来像是终止返回false。有没有办法让我检查为什么ExecutorService不会终止?我可以找出哪些线程仍在运行吗?没有安全的方法可以停止正在运行的线程而不影响进程其余部分的稳定性。这就是为什么
Thread#stop
早就被弃用的原因,也是为什么Executor服务只使用软的、协作的Thread#interrupt
机制的原因
您的线程必须主动检查是否请求了中断,并在结束之前执行适当的清理。或者,线程将调用一些可中断的JDK方法,这些方法将抛出
InterruptedException
,tread将正确地执行并结束它自己。没有安全的方法可以停止正在运行的线程而不干扰进程其余部分的稳定性。这就是为什么Thread#stop
早就被弃用的原因,也是为什么Executor服务只使用软的、协作的Thread#interrupt
机制的原因
您的线程必须主动检查是否请求了中断,并在结束之前执行适当的清理。或者,线程将调用一些可中断的JDK方法,这些方法将抛出InterruptedException
,tread将正确地执行并结束它自己。为什么Future.cancel()不能按您认为的方式工作。
Future cancel从正在运行的队列中删除任务。如果您的任务已经在运行,它将不会停止它。因此,cancel()是一个与中断不同的概念。正如Javadocs所说:
试图取消此任务的执行。如果
该任务已完成、已取消或可能无法执行
不能因为其他原因取消。如果成功,此任务
调用cancel时未启动,此任务不应运行。如果
任务已启动,然后使用MayInterruptFrunning参数
确定执行此任务的线程是否应
在试图停止任务时被中断。
你问的是如何打断别人。幸运的是,当您调用Future.cancel()时,它将调用中断方法。但您需要允许它带有MayInterruptFrunning标志,并且需要正确处理中断(见下文)
为什么要打断?
当您有一个长时间运行的任务需要停止时,或者当您有一个守护进程需要关闭时,以及其他示例中,在Java中中断线程非常有用
如何中断
要中断,请在线程上调用interrupt()。这是一个协作过程,因此您的代码必须为此做好准备。像这样:
myThread.interrupt();
责任代码
代码的责任是为任何中断做好准备。我想说的是,每当您有一个长时间运行的任务时,您都会插入一些中断准备代码,如下所示:
while (... something long...) {
... do something long
if (Thread.interrupted()) {
... stop doing what I'm doing...
}
}
如何停止我正在做的事情?
您有几个选择:
private void someMethodDeepDown() {
while (.. long running task .. ) {
... do lots of work ...
if (Thread.interrupted()) {
// oh no! an interrupt!
Thread.currentThread().interrupt();
throw new SomeOtherException();
}
}
}