I want to run a thread for some fixed amount of time. If it is not completed within that time, I want to either kill it, throw some exception, or handle it in some way. How
I was looking for an ExecutorService that can interrupt all timed out Runnables executed by it, but found none. After a few hours I created one as below. This class can be modified to enhance robustness.
public class TimedExecutorService extends ThreadPoolExecutor {
long timeout;
public TimedExecutorService(int numThreads, long timeout, TimeUnit unit) {
super(numThreads, numThreads, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue(numThreads + 1));
this.timeout = unit.toMillis(timeout);
}
@Override
protected void beforeExecute(Thread thread, Runnable runnable) {
Thread interruptionThread = new Thread(new Runnable() {
@Override
public void run() {
try {
// Wait until timeout and interrupt this thread
Thread.sleep(timeout);
System.out.println("The runnable times out.");
thread.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
interruptionThread.start();
}
}
Usage:
public static void main(String[] args) {
Runnable abcdRunnable = new Runnable() {
@Override
public void run() {
System.out.println("abcdRunnable started");
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
// logger.info("The runnable times out.");
}
System.out.println("abcdRunnable ended");
}
};
Runnable xyzwRunnable = new Runnable() {
@Override
public void run() {
System.out.println("xyzwRunnable started");
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
// logger.info("The runnable times out.");
}
System.out.println("xyzwRunnable ended");
}
};
int numThreads = 2, timeout = 5;
ExecutorService timedExecutor = new TimedExecutorService(numThreads, timeout, TimeUnit.SECONDS);
timedExecutor.execute(abcdRunnable);
timedExecutor.execute(xyzwRunnable);
timedExecutor.shutdown();
}