[concurrency-interest] Unreported RuntimeException if Future.get() is never invoked

Tim Peierls tim at peierls.net
Thu Dec 21 12:00:52 EST 2006

It's a minor point, but I think it would be better to restore the interrupt
flag in the IE catch clause in your example, with


Without this, if you run your FutureTask directly with ft.run(), an
interrupt of the current thread might be lost. I know that your intent is to
confine this FutureTask to the execute() call, but now you have an extra
constraint that maintainers of your code need to think about -- and what if
the ExecutorService implementation passed to the CancellableTask constructor
isn't as well-behaved as TPE? It's safer to abide by the interrupt handling
golden rule: propagate by throwing or restore the interrupt status.

Another way to handle unchecked exceptions and errors thrown by Runnables is
to wrap each submitted Runnable with a try-catch block. For example (off the
top of my head, uncompiled):

interface UncheckedHandler {
    caughtRuntimeException(Runnable r, RuntimeException e);
    caughtError(Runnable r, Error e);

class UncheckedHandlingTask implements Runnable {
    private final Runnable task;
    private final UncheckedHandler handler;

    public UncheckedHandlingTask(Runnable task, UncheckedHandler handler) {
        this.task = task;
        this.handler = handler;

    public void run() {
        try {
            task.run ();
        } catch (RuntimeException e) {
            handler.caughtRuntimeException(task, e);
            throw e;
        } catch (Error e) {
            handler.caughtError(task, e);
            throw e;

In Java 6, you can override the newTaskFor method of TPE (from
AbstractExecutorService) to perform this wrapping automatically, which
effectively gives you the ability to bind unchecked exception and error
handling behavior to a TPE instance.

In Java 5, you can get the same effect by wrapping your ExecutorService in
an AbstractExecutorService that wraps submitted Runnables and delegates to
the TPE.

Still another approach is to override TPE's afterExecute method. This is
simpler than wrapping Runnables, but the approach in the preceding paragraph
can be applied to any ExecutorService, not just TPE.


On 12/21/06, Kevin Condon <conivek at gmail.com> wrote:
> A co-worker and I, JCiP in hand, discovered that the solution to this
> is to extend FutureTask overriding the done() hook to check/log the
> exception and then use exec.execute(futureTask) instead of
> submit(this).  To do this, change the execute() method:
>   public void execute() {
>     FutureTask<?> futureTask = new FutureTask<?>(this, null) {
>       protected void done() {
>         try {
>           get();
>         } catch (ExecutionException ex) {
>           ex.getCause().printStackTrace();  // logging or handling of your
> choice
>         } catch (CancellationException ex) {
>           // ignore unless you want to log task cancellation here
>         } catch (InterruptedException ex) {
>           // ignore; we're done, so get() won't block or be interrupted
>         }
>       }
>     };
>     future = futureTask;
>     exec.execute(futureTask);
>   }
-------------- next part --------------
An HTML attachment was scrubbed...
URL: /pipermail/attachments/20061221/3fb936eb/attachment.html 

More information about the Concurrency-interest mailing list