1

I have multiple methods running concurrently on different threads. If an exception occurs and isn't handled on any of the threads, I want it to propagate back to the calling method (see example below).

public class Main {
    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(3);
        pool.execute(new Thread1Class());//Thread 1 of many
        //...
    }
}

class Thread1Class implements Runnable{
    @Override
    public void run() {
        try {
            throw new InterruptedException(); //How do I propogate this to the main method?
        } catch (InterruptedException e) {
            System.out.println("An unchecked exception was caught here");
        }
    }
}

The threads must implement Runnable since Callable will block the threads from running concurrently.

I followed the method of Overriding protected void afterExecute(Runnable r, Throwable t) shown as the accepted answer here: Handling exceptions from Java ExecutorService tasks. If I understand correct, this solution will only handle unchecked exceptions. How should I deal with the checked exceptions?

jlaufer
  • 89
  • 8
  • 1
    Re: "The threads must implement Runnable since Callable will block the threads from running concurrently": This sounds like a misunderstanding of some sort (though that doesn't really affect your question). – ruakh Aug 24 '22 at 03:07
  • In your linked question, the code does `throw new RuntimeException("Ouch! Got an error.");` - so why do you think that it can not handle unchecked exceptions? *RuntimeException and its subclasses are unchecked exceptions.* – Scary Wombat Aug 24 '22 at 03:18
  • @ruakh is there a way to use Callable and have all the threads run at the same time? If so, then that's the answer. – jlaufer Aug 24 '22 at 03:26
  • @ScaryWombat, In the last two sentences I mixed up checked/unchecked. It's corrected now. – jlaufer Aug 24 '22 at 03:28
  • @jlaufer ExecutorService has an [invokeAll](https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/util/concurrent/ExecutorService.html#invokeAll(java.util.Collection)) method for exactly that purpose. – VGR Aug 24 '22 at 17:46
  • @VGR invokeAll waits for all threads to finish before returning the result – jlaufer Aug 24 '22 at 19:34
  • I’m a little confused. How would you propagate an exception back to the caller without either waiting or returning a Future? – VGR Aug 25 '22 at 01:58
  • @VGR That is basically my question. I've learned that it is called a "leak" when an exception propagates from a thread to the caller. This has has negative connotation but in my case it is desirable. Only a runtime exception can propagate from a thread to the caller so checked exceptions must be wrapped as runtime exceptions to propagate per minhtrivo. These propagated exceptions are "uncaught exceptions". For an ExecutorService type, overriding afterExecute will handle the uncaught exception. For a regular Thread there are several options including Thread.SetDefaultUncaughtExceptionHandler. – jlaufer Aug 25 '22 at 13:10

1 Answers1

2

If I understand correct, this solution will only handle unchecked exceptions. How should I deal with the checked exceptions

No, the afterExecute(Runnable, Throwable) would catch any RuntimeException or checked exception. According to the docs at https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ThreadPoolExecutor.html

If non-null, the Throwable is the uncaught RuntimeException or Error that caused execution to terminate abruptly.

Edit:

Sorry for the misunderstanding,

If you want to propagate the checked exception to the caller, you would need to wrap it in a RuntimeException

 InterruptedException a;
 throw new RuntimeException("wrapped", a);

The executor:

protected void afterExecute(Runnable r, Throwable t){
      Throwable root = t.getCause();
}

Or you could create your own runtime exception type.

minh tri Vo
  • 524
  • 4
  • 11
  • Okay but if I write "throw new InterruptedException();" without the try/catch I have an unhandled exception. I can't write "throws InterruptedException()" in the overridden method. – jlaufer Aug 24 '22 at 03:34