Wait for cancel() on FutureTask Wait for cancel() on FutureTask multithreading multithreading

Wait for cancel() on FutureTask


Yes, CancellationException is thrown immediately. You may extend FutureTask to add get() method's version which waits until Callable's thread is finished.

public class ThreadWaitingFutureTask<T> extends FutureTask<T> {    private final Semaphore semaphore;    public ThreadWaitingFutureTask(Callable<T> callable) {        this(callable, new Semaphore(1));    }    public T getWithJoin() throws InterruptedException, ExecutionException {        try {            return super.get();        }        catch (CancellationException e) {            semaphore.acquire();            semaphore.release();            throw e;        }    }    private ThreadWaitingFutureTask(final Callable<T> callable,                 final Semaphore semaphore) {        super(new Callable<T>() {            public T call() throws Exception {                semaphore.acquire();                try {                    return callable.call();                }                finally {                    semaphore.release();                }            }        });        this.semaphore = semaphore;    }}


Aleksey's example works well. I wrote a variant with a constructor taking a Runnable (will return null) and showing how to directly block (join) on cancel():

public class FutureTaskCancelWaits<T> extends FutureTask<T> {    private final Semaphore semaphore;    public FutureTaskCancelWaits(Runnable runnable) {        this(Executors.callable(runnable, (T) null));    }    public FutureTaskCancelWaits(Callable<T> callable) {        this(callable, new Semaphore(1));    }    @Override    public boolean cancel(boolean mayInterruptIfRunning) {        // If the task was successfully cancelled, block here until call() returns        if (super.cancel(mayInterruptIfRunning)) {            try {                semaphore.acquire();                // All is well                return true;            } catch (InterruptedException e) {                // Interrupted while waiting...            } finally {                semaphore.release();            }        }        return false;    }    private FutureTaskCancelWaits(final Callable<T> callable, final Semaphore semaphore) {        super(new Callable<T>() {            public T call() throws Exception {                semaphore.acquire();                try {                    return callable.call();                } finally {                    semaphore.release();                }            }        });        this.semaphore = semaphore;    }}


It is thrown as soon as it is cancelled.

There is no easy way to know it has started and is finished. You can create a wrapper for you runnable to check its state.

final AtomicInteger state = new AtomicInteger();// in the runnablestate.incrementAndGet();try {    // do work} finally {   state.decrementAdnGet();}