ExecutorService that interrupts tasks after a timeout ExecutorService that interrupts tasks after a timeout multithreading multithreading

ExecutorService that interrupts tasks after a timeout


You can use a ScheduledExecutorService for this. First you would submit it only once to begin immediately and retain the future that is created. After that you can submit a new task that would cancel the retained future after some period of time.

 ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);  final Future handler = executor.submit(new Callable(){ ... }); executor.schedule(new Runnable(){     public void run(){         handler.cancel();     }       }, 10000, TimeUnit.MILLISECONDS);

This will execute your handler (main functionality to be interrupted) for 10 seconds, then will cancel (i.e. interrupt) that specific task.


Unfortunately the solution is flawed. There is a sort of bug with ScheduledThreadPoolExecutor, also reported in this question: cancelling a submitted task does not fully release the memory resources associated with the task; the resources are released only when the task expires.

If you therefore create a TimeoutThreadPoolExecutor with a fairly long expiration time (a typical usage), and submit tasks fast enough, you end up filling the memory - even though the tasks actually completed successfully.

You can see the problem with the following (very crude) test program:

public static void main(String[] args) throws InterruptedException {    ExecutorService service = new TimeoutThreadPoolExecutor(1, 1, 10, TimeUnit.SECONDS,             new LinkedBlockingQueue<Runnable>(), 10, TimeUnit.MINUTES);    //ExecutorService service = Executors.newFixedThreadPool(1);    try {        final AtomicInteger counter = new AtomicInteger();        for (long i = 0; i < 10000000; i++) {            service.submit(new Runnable() {                @Override                public void run() {                    counter.incrementAndGet();                }            });            if (i % 10000 == 0) {                System.out.println(i + "/" + counter.get());                while (i > counter.get()) {                    Thread.sleep(10);                }            }        }    } finally {        service.shutdown();    }}

The program exhausts the available memory, although it waits for the spawned Runnables to complete.

I though about this for a while, but unfortunately I could not come up with a good solution.

EDIT:I found out this issue was reported as JDK bug 6602600, and appears to have been fixed very recently.


Wrap the task in FutureTask and you can specify timeout for the FutureTask. Look at the example in my answer to this question,

java native Process timeout