【问题标题】:Stop ExecutorService threads when one thread fails. & return the exception当一个线程失败时停止 ExecutorService 线程。 & 返回异常
【发布时间】:2015-07-18 16:24:54
【问题描述】:

如果任何提交的线程抛出异常,它不会返回异常。

我想为我的项目编写一段代码,如果任何线程执行失败,它应该在那里抛出异常并且它应该停止所有正在运行和计划的线程。

ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
 Thread t = new Thread(new MyObject());
 executorService.submit(t);
}

我是这样写MyObject的..,

public class MyObject implements Runnable {   
    public void run() {
         throw new NullPointerException("Sample NullPointerException");
    }
}

这对我的目标来说是正确的实现吗...????? 我想实现这个目标,请给我一些指点。

提前谢谢....!!

【问题讨论】:

    标签: java multithreading exception-handling threadpool threadpoolexecutor


    【解决方案1】:

    这是您可以考虑的事情。这里我使用的是 CallableTask 而不是 Thread。

        public static void main(String[] args) {
                ExecutorService executorService = Executors.newFixedThreadPool(10);
                Set<Future<Void>> futureSet = new HashSet<Future<Void>>();
    
                for (int i = 0; i < 9; i++) {
                    CallableTask1 task = new CallableTask1();
                    futureSet.add(executorService.submit(task));
                }
    
                CallableTask2 task2 = new CallableTask2();
                futureSet.add(executorService.submit(task2));
    
                boolean flag = false;
                for (Future<Void> future : futureSet ) {
                    try {
                        future.get();
                    } catch (InterruptedException e) {
                        System.out.println("Interrupted");
                    } catch (ExecutionException e) {
                        System.out.println("Exception thrown from the thread");
                        flag = true;
                        break;
                    }
                }
    
                if(flag) {
                    for (Future<Void> future : futureSet) {
                        future.cancel(true);
                    }
                }
          }
    

    在这里,我使用两个类来证明这是有效的。当一个任务抛出异常时,永远运行的任务也会停止运行。

    class CallableTask1 implements Callable<Void> {
    
        @Override
        public Void call() throws Exception {
            throw new NullPointerException("Sample NullPointerException");
        }
    }
    
    
    class CallableTask2 implements Callable<Void> {
    
        @Override
        public Void call() throws Exception {
            while (true){
                System.out.println("THIS IS RUNNING");
                Thread.sleep(5000);
    
            }
        }
    }
    

    但这有它自己的局限性。由于“future.get()”顺序执行,这段代码将等待轮到它抛出异常。

    最佳情况:在第一个future.get()中抛出异常,其他任务将被取消。

    最坏的情况:在最后一个future.get()中抛出一个异常,到时候抛出一个异常,所有其他执行完成的任务。

    优化:识别可以抛出异常的任务并等待这些任务仅取消所有其他任务。

    如果你的 run 方法中有 while ,那么最好的方法是共享一个标志并在其上中断。查看this答案了解更多信息。

    【讨论】:

    • 我可以看到可能使用了共享标志,如果已设置,可能会在每个 Callable 中跳过执行...? :)
    • 如果我无法确定哪个线程可能会失败,那么如何优化代码?
    猜你喜欢
    • 2021-11-09
    • 1970-01-01
    • 1970-01-01
    • 2016-08-31
    • 2011-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-10
    相关资源
    最近更新 更多