TimedRun.java avoid canceling task directly, instead, it submits the task to a standard ExecutorService implementation (Executors.newCachedThreadPool() here) and manage the result, Exception and task cancellation via the Future returned by taskExec.submit(r). This approach works on interfaces, which is how business makes life easy.
CHAP7>cat TimedRun.java
import java.util.concurrent.*;
/**
* TimedRun
* <p/>
* Cancelling a task using Future
*/
public class TimedRun {
private static final ExecutorService taskExec = Executors.newCachedThreadPool();
private static final ExecutorService exec = Executors.newFixedThreadPool(2);
public static void timedRun(Runnable r,
long timeout, TimeUnit unit)
throws InterruptedException {
Future<?> task = taskExec.submit(r);
try {
task.get(timeout, unit);
} catch (TimeoutException e) {
System.out.println("task will be cancelled below");
} catch (ExecutionException e) {
System.out.println("exception thrown in task; rethrow");
throw new RuntimeException(e.getCause());
} finally {
System.out.println("Harmless if task already completed");
task.cancel(true); // interrupt if running
}
}
public static void main(String...args) {
Runnable r = new Runnable() {
@Override
public void run() {
try {
System.out.println("worker thread run runnable1: "
+ Thread.currentThread());
// Runnable r2 = () ->
// System.out.println(Thread.currentThread() +
// ": suppose to interrupt me.");
Runnable r2 = () -> {
int i = 10 / 0;
};
// Runnable r2 = () -> {
// try {
// System.out.println("new thread run submitted runnable: "
// + Thread.currentThread());
// Thread.sleep(5000);
// } catch(Exception e) {
// e.printStackTrace();
// }
// };
timedRun(r2, 1, TimeUnit.SECONDS);
} catch (Exception e) {
e.printStackTrace();
}
}
};
exec.submit(r);
exec.submit(() -> {
try {
Thread.sleep(2000);
} catch(InterruptedException e) {
System.out.println(Thread.currentThread() + ": the victim could be me with other pool size and submit order!");
e.printStackTrace();
}}
);
exec.submit(() -> {
try {
Thread.sleep(5000);
} catch(InterruptedException e) {
System.out.println(Thread.currentThread() + ": however, I was interrupted!");
e.printStackTrace();
}}
);
try {
exec.shutdown();
exec.awaitTermination(10, TimeUnit.SECONDS);
taskExec.shutdown();
taskExec.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
CHAP7>javac TimedRun.java
CHAP7>java TimedRun
worker thread run runnable1: Thread[pool-2-thread-1,5,main]
exception thrown in task; rethrow
Harmless if task already completed
java.lang.RuntimeException: java.lang.ArithmeticException: / by zero
at TimedRun.timedRun(TimedRun.java:21)
at TimedRun$1.run(TimedRun.java:51)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ArithmeticException: / by zero
at TimedRun$1.lambda$run$0(TimedRun.java:39)
at TimedRun$1$$Lambda$1/1128072020.run(Unknown Source)
... 5 more
CHAP7>