0

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();
        }
    }
}
Sumeet Kumar Yadav
  • 11,912
  • 6
  • 43
  • 80

2 Answers2

1

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();
                }
            }
zysaaa
  • 1,777
  • 2
  • 8
  • 19
  • Could you please explain about isDone method , is it only true when task is computed and executed ? There could be chance that isDone is false i am putting sleep in each task execution . – Sumeet Kumar Yadav Jan 03 '22 at 01:50
  • In ExecutionException catch block I am able to get error message , but how to get information for input type the error is thrown .Like i=7 or 14 – Sumeet Kumar Yadav Jan 03 '22 at 01:58
  • ```IsDone```: Returns true if this task completed. Completion may be due to normal termination, an exception, or cancellation -- in all of these cases, this method will return true. You don't need to use ```isDone``` to determine whether the task is complete, ```get``` will block until the task execution is complete – zysaaa Jan 03 '22 at 02:00
  • 1
    And you should use ```if(i%7==0) ``` instead of ```if(i/7==0) ``` – zysaaa Jan 03 '22 at 02:01
  • ohh yeah .. i%7 is correct . Thank you ``` IsDone ``` Returns true if this task completed. In my example why its returning true as its blocked for a second . IsDone checks what task completion . – Sumeet Kumar Yadav Jan 03 '22 at 02:05
  • 2
    No need to use ```isDone```, because you already use ```executorService#invokeAll```. ```InvokeAll ``` blocks until all tasks are complete. – zysaaa Jan 03 '22 at 02:14
  • Is there any way to know for which input error is thrown. Is there any better way to do error handling – Sumeet Kumar Yadav Jan 03 '22 at 02:21
  • 1
    Now that you have defined your own exception class, maybe you can pass the wrong input to your exception class, and get it in catch block, for example: ```Throwable cause = e.getCause(); if (cause instanceof MyException) { System.out.println(((MyException) cause).getErrorInput()); }```. You can refer to other similar questions : [what-is-the-best-way-to-handle-an-executionexception](https://stackoverflow.com/questions/10437890/what-is-the-best-way-to-handle-an-executionexception) – zysaaa Jan 03 '22 at 02:39
0

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


    }
}
yao Mr
  • 26
  • 2