【问题标题】:cancelling a future task in java [duplicate]在java中取消未来的任务[重复]
【发布时间】:2017-07-03 11:13:52
【问题描述】:

我想取消提交给 ExecutorService 的任务,从而允许相应的线程从队列中选择一个新任务。

现在这个问题在这个论坛上已经回答了很多次了......就像检查Thread.currentThread().interrupt()catch (InterruptedException e)一样。但是,如果控制流跨越多个方法,那么进行这些检查会使代码变得笨拙。因此,如果可能的话,请在 java 中提出一些优雅的方法来实现此功能。

我面临的问题是 future.cancel 实际上不会取消任务。相反,它只是将InterruptedException 发送给正在执行的任务,任务负责将自己标记为完成并释放线程。

所以我所做的是,每当在执行过程中的任何地方抛出异常时,我都必须放置下面的代码块,这显然看起来不太好!

if(e instanceof InterruptedException) {
                    throw e;
                }

那么,如何在下面的代码 sn-p 中实现这个功能:

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 {

    }

【问题讨论】:

    标签: java multithreading exception executorservice futuretask


    【解决方案1】:

    你打断Callable没关系,因为到那时已经太晚了

    try{
      MyClass2 myClass2 = new MyClass2();
      myClass2.method2();
    } catch (Exception e){
    

    您在Thread.sleep(2000) 之后对future1.cancel(true); 的调用实际上并没有取消 正在进行的 任务(在这种情况下是您的method2 调用),它只意味着它应该在开始之前就被取消了。

    文档指出了这一点 https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html#cancel(boolean)

    尝试取消此任务的执行。如果任务已完成、已被取消或由于其他原因无法取消,则此尝试将失败。如果成功,并且在调用取消时此任务尚未启动,则此任务不应该运行。如果任务已经启动,则 mayInterruptIfRunning 参数决定是否应该中断执行该任务的线程以尝试停止该任务。

    如果你想取消一个正在进行的任务,你想使用volatile boolean 标志或类似的东西。

    【讨论】:

    • future1.cancel(true) 肯定会发送 InterruptedException,因为主线程只休眠了 2000 毫秒,而方法 3 需要 10000 毫秒才能完成。现在method3将检查异常是否为instanceof InterruptedException。如果是,那么它将把它传递给调用者(方法2)。我不想在整个工作流程中的任何地方都保留此检查以最终将其传递给 MyClass1.call() 方法。这个世界上还有其他优雅的方式来实现这个功能吗??
    • @gautam - 使用回调机制。将对象传递给其他类并在 InterruptedException 期间捕获方法。回调机制参考stackoverflow.com/questions/36449040/…
    猜你喜欢
    • 2020-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-24
    • 1970-01-01
    • 1970-01-01
    • 2018-11-30
    相关资源
    最近更新 更多