Custom Undo for FutureTask

I implemented custom cancellation logic as described in Concurrency in practice.

Encapsulating custom cancellation in a task using newTaskFor .

This works fine, and I can call cancellation in the future, and the task is canceled as expected. I need to be able to destroy my executing service, which I use by calling the "shutdownNow" method, but this method just calls interupt for the threads, which means my custom undo logic is never called. Since my tasks use non-blocking sockets, thread interruption does not work, so I have a custom undo logic.

Is there a simple solution to canceling all current tasks. I tried to rewrite the shutdown method to ThreadPoolExecutor, but I do not have access to the list of workers. I would like to be able to cancel everything by closing the artist, since he is used in several places to send tasks, is there a simple solution for this?

+4
source share
1 answer

As John noted, it would be better if you could interrupt your tasks. Then you can simply rely on ThreadPoolExecutor to interrupt all worker threads to arrange for their cancellation.

If this is not possible, you can add additional logic to the ThreadPoolExecutor to achieve what you want. This is somewhat related and may not be very pretty for some (and may hurt performance a bit), but I think it will do its job. I think that basically you need to keep a list of active tasks yourself. The key is to override the beforeExecute () and afterExecute () methods:

public class MyExecutor extends ThreadPoolExecutor { private final Queue<RunnableFuture> activeTasks = new LinkedBlockingQueue<RunnableFuture>(); ... protected void beforeExecute(Thread t, Runnable r) { RunnableFuture task = (RunnableFuture)r; activeTasks.add(task); } protected void afterExecute(Thread t, Runnable r) { RunnableFuture task = (RunnableFuture)r; activeTasks.remove(task); } public void cancelAllActiveTasks() { for (RunnableFuture f: activeTasks) { f.cancel(true); // invokes your custom cancellation logic } } 

You can call cancelAllActiveTasks () or override shutDownNow () to call it. The only thing I don’t like about this is to remove the task from the queue, as this is not a constant time operation.

+1
source

All Articles