Site Search:

TimedRun1.java

Back>

In the following example, timedRun method try to run an arbitrary Runnable for a given amount of time. It runs the task in the calling thread and schedules a cancellation task to interrupt it after a given amount of time. The method timedRun can be called from an arbitrary thread, in this case, it is called from one of the worker threads in newFixedThreadPool with size 2. If the runnable completes before the timeout (in this case indeed,  running System.out.println(Thread.currentThread() + ": suppose to interrupt me." takes no time), the cancellation task that interrupts the thread in which the timedRun was called went off after timedRun has returned to its caller. When the delayed interrupt finally run, the worker thread has already been executing the next submitted Runnable (Thread.sleep(5000);), the interruption went off on a totally irrelevant Runnable instead of the intended Runnable.

CHAP7>cat TimedRun1.java 
import java.util.concurrent.*;

/**
 * InterruptBorrowedThread
 * <p/>
 * Scheduling an interrupt on a borrowed thread
 */
public class TimedRun1 {
    private static final ExecutorService exec = Executors.newFixedThreadPool(2);
    private static final ScheduledExecutorService cancelExec = Executors.newScheduledThreadPool(1);

    public static void timedRun(Runnable r,
                                long timeout, TimeUnit unit) {
        final Thread taskThread = Thread.currentThread();
        cancelExec.schedule(new Runnable() {
            public void run() {
                taskThread.interrupt();
            }
        }, timeout, unit);
        r.run();
    }
    
    public static void main(String...args) {
        exec.submit(() -> timedRun(() -> System.out.println(Thread.currentThread() + ": suppose to interrupt me."), 1, TimeUnit.SECONDS));
        
        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);
            cancelExec.shutdown();
            cancelExec.awaitTermination(10, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
CHAP7>javac TimedRun1.java 
CHAP7>java TimedRun1
Thread[pool-1-thread-1,5,main]: suppose to interrupt me.
Thread[pool-1-thread-1,5,main]: however, I was interrupted!
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at TimedRun1.lambda$main$3(TimedRun1.java:37)
at TimedRun1$$Lambda$4/41359092.run(Unknown Source)
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)

CHAP7>