This is a simplified example I did to expose my problem. I have some task doSomeWork() that I handle in a multihreading fashion using ExecutorService (4 threads at a time max). However, if any of the threads/tasks generates an exception, I would like to:
Stop any further tasks from being processed.
Catch the exception at the main thread level.
public static void main(String[] args) { final ExecutorService threadPool = Executors.newFixedThreadPool(4); final ExecutorCompletionService<Void> completionService = new ExecutorCompletionService<>(threadPool); try { for (int i = 0; i < 10; i++) { int b = i; completionService.submit(() -> doSomeWork(b)); } threadPool.shutdown(); threadPool.awaitTermination(8, TimeUnit.HOURS); System.exit(0); } catch (Exception e) { System.out.println("Something wrong happened: " + e.getMessage()); } System.exit(1); } //This function have 50% odds of throwing an exception public static Void doSomeWork(int i) throws Exception { Thread.sleep(500); if ((Math.random() > 0.5)) { System.out.println("I have reached indice: " + i); } else { throw new Exception("I couldn't handle indice " + i); } return null; }
Currently, an execution would output something like this:
I have reached indice: 0
I have reached indice: 2
I have reached indice: 1
I have reached indice: 4
I have reached indice: 6
I have reached indice: 7
I have reached indice: 5
I have reached indice: 9
As you can see, indice 3 is missing, nevertheless the execution of the remaining threads completed. It also didn't output anything about the exception.
My desired output would be something like this:
I have reached indice: 0
I have reached indice: 2
I have reached indice: 1
Something wrong happened: I couldn't handle indice 3
Other solutions I found around this problem were using a callable with a future but in a blocking fashion. I can't block the execution of other threads while waiting for the future otherwise this whole multithreading is pointless.