Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ExecutorService that interrupts tasks after a timeout

I'm looking for an ExecutorService implementation that can be provided with a timeout. Tasks that are submitted to the ExecutorService are interrupted if they take longer than the timeout to run. Implementing such a beast isn't such a difficult task, but I'm wondering if anybody knows of an existing implementation.

Here's what I came up with based on some of the discussion below. Any comments?

import java.util.List; import java.util.concurrent.*;  public class TimeoutThreadPoolExecutor extends ThreadPoolExecutor {     private final long timeout;     private final TimeUnit timeoutUnit;      private final ScheduledExecutorService timeoutExecutor = Executors.newSingleThreadScheduledExecutor();     private final ConcurrentMap<Runnable, ScheduledFuture> runningTasks = new ConcurrentHashMap<Runnable, ScheduledFuture>();      public TimeoutThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, long timeout, TimeUnit timeoutUnit) {         super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);         this.timeout = timeout;         this.timeoutUnit = timeoutUnit;     }      public TimeoutThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, long timeout, TimeUnit timeoutUnit) {         super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);         this.timeout = timeout;         this.timeoutUnit = timeoutUnit;     }      public TimeoutThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler, long timeout, TimeUnit timeoutUnit) {         super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);         this.timeout = timeout;         this.timeoutUnit = timeoutUnit;     }      public TimeoutThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler, long timeout, TimeUnit timeoutUnit) {         super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);         this.timeout = timeout;         this.timeoutUnit = timeoutUnit;     }      @Override     public void shutdown() {         timeoutExecutor.shutdown();         super.shutdown();     }      @Override     public List<Runnable> shutdownNow() {         timeoutExecutor.shutdownNow();         return super.shutdownNow();     }      @Override     protected void beforeExecute(Thread t, Runnable r) {         if(timeout > 0) {             final ScheduledFuture<?> scheduled = timeoutExecutor.schedule(new TimeoutTask(t), timeout, timeoutUnit);             runningTasks.put(r, scheduled);         }     }      @Override     protected void afterExecute(Runnable r, Throwable t) {         ScheduledFuture timeoutTask = runningTasks.remove(r);         if(timeoutTask != null) {             timeoutTask.cancel(false);         }     }      class TimeoutTask implements Runnable {         private final Thread thread;          public TimeoutTask(Thread thread) {             this.thread = thread;         }          @Override         public void run() {             thread.interrupt();         }     } } 
like image 998
Edward Dale Avatar asked May 03 '10 14:05

Edward Dale


People also ask

Does ExecutorService shutdown automatically?

Using shutdown() and awaitTermination​() In general, the ExecutorService will not be automatically destroyed when there is no task to process. It will stay alive and wait for new tasks to come.

How do I interrupt ExecutorService?

Another way to interrupt the executor's internally managed thread(s) is to call the shutdownNow(..) method on your ExecutorService . Note, however, that as opposed to @erickson's solution, this will result in the whole ThreadPoolExecutor becoming unfit for further use.

Which method of ExecutorService is called to check that all tasks are complete following shutdown?

When using an Executor, we can shut it down by calling the shutdown() or shutdownNow() methods. Although, it won't wait until all threads stop executing. Waiting for existing threads to complete their execution can be achieved by using the awaitTermination() method.

What does ExecutorService shutdown do?

Two different methods are provided for shutting down an ExecutorService. The shutdown() method will allow previously submitted tasks to execute before terminating, while the shutdownNow() method prevents waiting tasks from starting and attempts to stop currently executing tasks.


2 Answers

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.

like image 140
John Vint Avatar answered Sep 29 '22 19:09

John Vint


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

like image 24
ZZ Coder Avatar answered Sep 29 '22 18:09

ZZ Coder