Search code examples
javamultithreadingcollectionsthreadpooljava-threads

Java ExecutorService invokeAll multiple task resolv


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

Solution

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