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();
}
}
}
CodePudding user response:
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();
}
}
CodePudding user response:
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();
}
}
}
}