} catch (final InterruptedException e) {
e.printStackTrace();
} catch (final ExecutionException e) {
- e.printStackTrace();
//The exception thrown in the threads is caught by the main thread here.
System.out.println("Exception from task " + i + ": "
+ Thread.currentThread().getName() + "\n");
+ final Throwable cause = e.getCause();
+ // try { Uncomment this code in order to run the test. :(
+ this.launderThrowable(cause);
+ // } catch (final Throwable exception) {
+ // exception.printStackTrace();
+ // }
} finally {
future[i].cancel(true);
}
// After exec.shutdown if we try to execute more tasks a RejectedExecutionException
// exception will be thrown to the main thread.
- System.out.println("Going to receive a RejectedExecutionException");
+ System.out.println("Going to receive a RejectedExecutionException ");
for (int i = 0; i < 3; i++) {
this.exec.execute(new ThreadExecutor(i));
}
}
+ // Before calling launderThrowable, Preloader tests for the known checked
+ // exceptions and rethrows
+ // them. That leaves only unchecked exceptions, which Preloader handles by
+ // calling launderThrowable and throwing the
+ // result. If the Throwable passed to launderThrowable is an Error,
+ // launderThrowable rethrows it directly; if it is not a
+ // RuntimeException, it throws an IllegalStateException to indicate a logic
+ // error. That leaves only RuntimeException,
+ // which launderThrowable returns to its caller, and which the caller
+ // generally rethrows
+
+ /**
+ * If the Throwable is an Error, throw it; if it is a RuntimeException
+ * return it, otherwise throw IllegalStateException
+ */
+ private RuntimeException launderThrowable(final Throwable exception) {
+ exception.printStackTrace();
+ if (exception instanceof RuntimeException)
+ return (RuntimeException) exception;
+ else if (exception instanceof Error)
+ throw (Error) exception;
+ else
+ throw new IllegalStateException("Not unchecked", exception);
+ }
+
+
private class ThreadExecutor implements Runnable {
int i;