【问题标题】:Java ExecutorService invokeAll multiple task resolvJava ExecutorService invokeAll 多任务解析
【发布时间】:2022-01-03 01:19:04
【问题描述】:

我正在使用执行器服务来并行运行任务。并行运行方法接受输入整数并返回整数。由于并行任务有返回类型,所以我使用了 Callable 匿名类。您可以在下面的示例中看到 ExecutorServiceExample task(int i ) 是从 executer 调用的。任务方法也有1秒的等待时间并抛出i==7;的异常

在下面的实现中,我使用 invokeAll 并使用 isDone 并尝试收集数据。

下面的程序抛出IllegalMonitorStateException

Future 任务迭代和检查 isDone 和 get() 有什么问题。如何处理特定调用的异常。我想并行运行所有 1 到 14 个任务,并在所有完成时收集返回返回类型。此外,如果出现错误,如何知道它抛出异常的输入,例如(7 和 14)

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;

class MyException extends Exception{
    MyException(String message) {
        super(message);
    }
}

public class ExecutorServiceExample {

    public int task(int i) throws MyException, InterruptedException {
        System.out.println("Running task.."+i);
        wait(1000);
        if(i%7==0) {
            throw new MyException("multiple of 7 not allowed");
        }

        return i;
    }

    public static void main(String[] args) {

        ExecutorService executorService = Executors.newFixedThreadPool(10);

        List<Callable<Integer>> tasks = Arrays.asList(1,2,3,4,5,6,7,8,9,10,11,12,13,14).stream().map(id->{
           return new Callable<Integer>() {
               @Override
               public Integer call() throws Exception {
                   ExecutorServiceExample executorServiceExample = new ExecutorServiceExample();
                   return executorServiceExample.task(id);
               }
           };
        }).collect(Collectors.toList());
        
        try{
            List<Future<Integer>> results = executorService.invokeAll(tasks);

            for (Future<Integer> task: results) {
                if(task.isDone()){
                    System.out.println(task.get());
                }
            }

        }catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }finally {
            executorService.shutdown();
        }
    }
}

【问题讨论】:

    标签: java multithreading collections threadpool java-threads


    【解决方案1】:

    事实上,每个任务都会产生一个IllegalMonitorStateException,因为您没有在synchronized 块中调用wait 方法:IllegalMonitorStateException on wait() call。也许你应该使用sleep 而不是wait

    ExecutionExceptionfuture#get 抛出。所以如果你缩小try-catch的范围,实际上会捕获14个异常:

               for (Future<Integer> task: results) {
                    try {
                        System.out.println(task.get());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (ExecutionException e) {
                        e.printStackTrace();
                    }
                }
    

    【讨论】:

    • 你能解释一下isDone方法吗,它只在计算和执行任务时才成立? isDone 可能是错误的,我在每个任务执行中都设置了睡眠。
    • 在 ExecutionException 捕获块中,我能够得到错误消息,但是如何获取输入类型的信息时会抛出错误。像 i=7 或 14
    • 你应该使用if(i%7==0) 而不是if(i/7==0)
    • 不需要使用isDone,因为你已经使用了executorService#invokeAllInvokeAll 阻塞,直到所有任务完成。
    • 现在您已经定义了自己的异常类,也许您可​​以将错误的输入传递给您的异常类,并在 catch 块中获取它,例如:Throwable cause = e.getCause(); if (cause instanceof MyException) { System.out.println(((MyException) cause).getErrorInput()); }。其他类似问题可以参考:what-is-the-best-way-to-handle-an-executionexception
    【解决方案2】:

    我不知道你为什么这样设计它。但显然,它有很多问题。 i/7==0 or i % 7 ==0? examples 不是锁,为什么要使用等待? 'invokeAll' 返回的期货必须完成,但在调用 get 时可能会出现异常。 这是你想要的吗?

    import java.util.List;
    import java.util.concurrent.*;
    import java.util.stream.Collectors;
    import java.util.stream.Stream;
    
    class MyException extends Exception {
        MyException(String message) {
            super(message);
        }
    }
    
    public class ExecutorServiceExample {
    
        public int task(int i) throws MyException, InterruptedException {
            TimeUnit.MILLISECONDS.sleep(1000);
            if (i % 7 == 0) {
                throw new MyException("multiple of 7 not allowed");
            }
    
            return i;
        }
    
        public static void main(String[] args) throws InterruptedException {
    
            ExecutorService executorService = Executors.newFixedThreadPool(10);
    
            List<Callable<Integer>> tasks = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)
                    .map(id -> (Callable<Integer>) () -> {
                        ExecutorServiceExample executorServiceExample = new ExecutorServiceExample();
                        return executorServiceExample.task(id);
                    }).collect(Collectors.toList());
            List<Future<Integer>> results = executorService.invokeAll(tasks);
            executorService.shutdown();
            for (Future<Integer> task : results) {
                try {
                    System.out.println(task.get());
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }
            }
    
    
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-17
      • 2014-11-15
      相关资源
      最近更新 更多