我想取消提交给ExecutorService的任务,从而允许相应的线程从队列中选择一个新任务。
现在这个问题在这个论坛上得到了很多次回答....比如检查Thread.currentThread().interrupt()
或catch (InterruptedException e)
。但是,如果控制流跨越多种方法,那么进行这些检查会使代码变得笨拙。因此,如果可能的话,请在java中建议一些优雅的方法来实现此功能。
我面临的问题是future.cancel实际上不会取消任务。相反,它只是向执行任务发送InterruptedException
,任务有责任标记自己完成并释放线程。
所以我所做的是,每当在执行中的任何地方抛出异常时,我都必须放下下面的代码块,这显然看起来不太好!
if(e instanceof InterruptedException) {
throw e;
}
那么,如何在以下代码片段中实现此功能:
public class MonitoringInParallelExp {
public static void main(String[] args) throws InterruptedException {
MyClass1 myClass1 = new MyClass1();
ExecutorService service = Executors.newFixedThreadPool(1);
Future<String> future1 = service.submit(myClass1);
Thread.sleep(2000);
System.out.println("calling cancel in Main");
future1.cancel(true);
System.out.println("finally called cancel in Main");
service.shutdown();
}
}
class MyClass1 implements Callable<String> {
@Override
public String call() throws Exception {
try{
MyClass2 myClass2 = new MyClass2();
myClass2.method2();
} catch (Exception e){
if(e instanceof InterruptedException) {
System.out.println("call:"+"e instanceof InterruptedException="+"true");
throw e;
}
System.out.println("Got exception in method1. " + e);
}
System.out.println("returning Myclass1.method1.exit");
return "Myclass1.method1.exit";
}
}
class MyClass2 {
public void method2() throws Exception{
try{
MyClass3 myClass3 = new MyClass3();
myClass3.method3();
} catch (Exception e){
if(e instanceof InterruptedException) {
System.out.println("method2:"+"e instanceof InterruptedException="+"true");
throw e;
}
System.out.println("Got exception in method2. " + e);
// in case the exception isn't InterruptedExceptionm, do some work here
}
}
}
class MyClass3 {
public void method3() throws Exception{
try{
Thread.sleep(10000);
} catch (Exception e){
if(e instanceof InterruptedException) {
System.out.println("method3:"+"e instanceof InterruptedException="+"true");
throw e;
}
System.out.println("Got exception in method3. " + e);
throw new MyException();
}
}
}
class MyException extends Exception {
}
答案 0 :(得分:4)
如果你中断了Callable
并不重要,因为那时已经太晚了
try{
MyClass2 myClass2 = new MyClass2();
myClass2.method2();
} catch (Exception e){
future1.cancel(true);
之后对Thread.sleep(2000)
的来电实际上取消 正在进行的任务(在这种情况下是您的method2
来电)它只意味着它应该在它开始之前被取消。
文档指出了这一点 https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html#cancel(boolean)
尝试取消执行此任务。如果任务已完成,已取消或由于某些其他原因无法取消,则此尝试将失败。如果成功,并且在调用cancel时此任务尚未启动,则此任务永远不会运行。如果任务已经启动,则mayInterruptIfRunning参数确定执行此任务的线程是否应该在尝试停止任务时被中断。
如果您要取消正在进行的任务,您想使用volatile boolean
标志或类似的东西。