Java ExecutorService invokeAll multiple task resolv

1.7k views Asked by At

I am using executer service to run task in parallel . The parallel running method takes input integer and returns integer . As parallel task has return type , so I have used Callable anonymous class . You can see in below example ExecutorServiceExample task(int i ) is called from executer . The task method also has waiting time for 1 second and throws exception for i==7;

In below implementation I am using invokeAll and using isDone and get trying to collect data .

The below program throws IllegalMonitorStateException .

What is wrong with Future task iteration and checking isDone and get() . How to handle exception of specific call . I want to run all 1 to 14 task in parallel and on all complete collect the return return type . Also in case of error what to know the input for which it thown exception like(7 and 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();
        }
    }
}
2

There are 2 answers

8
zysaaa On BEST ANSWER

In fact, every task produced an IllegalMonitorStateException because you did not call wait method in a synchronized block: IllegalMonitorStateException on wait() call. Maybe you should use sleep instead of wait.

ExecutionException is thrown by future#get. So if you narrow the scope of try-catch, 14 exceptions will actually be caught:

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

I don't know why you designed it like this. But obviously, it has many problems. i/7==0 or i % 7 ==0? examples aren't locks, so why use wait? the futures that the returns of 'invokeAll' are must be done but maybe get an exception when invoke get. Is this what you want?

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();
            }
        }


    }
}