Search code examples
javafuturetask

How do I get FutureTask to return after TimeoutException?


In the code below, I'm catching a TimeoutException after 100 seconds as intended. At this point I would expect the code to exit from main and the program to terminate but it keeps printing to the console. How do I get the task to stop executing after timeout?

private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool();

private static <T> T timedCall(Callable<T> c, long timeout, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException {
    FutureTask<T> task = new FutureTask<T>(c);
    THREAD_POOL.execute(task);
    return task.get(timeout, timeUnit);
}


public static void main(String[] args) {

    try {
        int returnCode = timedCall(new Callable<Integer>() {
            public Integer call() throws Exception {
                for (int i=0; i < 1000000; i++) {
                    System.out.println(new java.util.Date());
                    Thread.sleep(1000);
                }
                return 0;
            }
        }, 100, TimeUnit.SECONDS);
    } catch (Exception e) {
        e.printStackTrace();
        return;
    }


}

Solution

  • You need to cancel your task on timeout (and interrupt its thread). That's what cancel(true) method is for. :

    private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool();
    
    private static <T> T timedCall(FutureTask<T> task, long timeout, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException {
        THREAD_POOL.execute(task);
        return task.get(timeout, timeUnit);
    }
    
    
    public static void main(String[] args) {
            try {
                FutureTask<Integer> task = new FutureTask<Integer>(new Callable<Integer>() {
                    public Integer call() throws Exception {
                            for (int i=0; i < 1000000; i++) {
                                    if (Thread.interrupted()) return 1;
                                    System.out.println(new java.util.Date());
                                    Thread.sleep(1000);
                            }
                            return 0;
                    }
                });
                int returnCode = timedCall(task, 100, TimeUnit.SECONDS);
            } catch (Exception e) {
                    e.printStackTrace();
                    task.cancel(true);
            }
            return;
    }