Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Executor Service - timeout of thread

While I was exploring ExecutorService, I encountered a method Future.get() which accepts the timeout.

The Java doc of this method says


Waits if necessary for at most the given time for the computation to complete, and then retrieves its result, if available.

Parameters:

timeout the maximum time to wait

unit the time unit of the timeout argument


As per my understanding, we are imposing a timeout on the callable, we submit to the ExecutorService so that, my callable will interrupt after the specified time(timeout) has passed

But as per below code, the longMethod() seems to be running beyond the timeout(2 seconds), and I am really confused understanding this. Can anyone please point me to the right path?

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class Timeout implements Callable<String> {

    public void longMethod() {
        for(int i=0; i< Integer.MAX_VALUE; i++) {
            System.out.println("a");
        }
    }

    @Override
    public String call() throws Exception {
        longMethod();
        return "done";
    }


    /**
     * @param args
     */
    public static void main(String[] args) {
        ExecutorService service = Executors.newSingleThreadExecutor();

        try {
            service.submit(new Timeout()).get(2, TimeUnit.SECONDS);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}
like image 303
sanbhat Avatar asked Apr 29 '13 11:04

sanbhat


1 Answers

my callable will interrupt after the specified time(timeout) has passed

Not true. The task will continue to execute, instead you will have a null string after the timeout.

If you want to cancel it:

  timeout.cancel(true) //Timeout timeout = new Timeout();

P.S. As you have it right now this interrupt will have no effect what so ever. You are not checking it in any way.

For example this code takes into account interrupts:

    private static final class MyCallable implements Callable<String>{

    @Override
    public String call() throws Exception {
        StringBuilder builder = new StringBuilder();
        try{
            for(int i=0;i<Integer.MAX_VALUE;++i){
                builder.append("a");
                Thread.sleep(100);
            }
        }catch(InterruptedException e){
            System.out.println("Thread was interrupted");
        }
        return builder.toString();
    }
}

And then:

        ExecutorService service = Executors.newFixedThreadPool(1);
    MyCallable myCallable = new MyCallable();
    Future<String> futureResult = service.submit(myCallable);
    String result = null;
    try{
        result = futureResult.get(1000, TimeUnit.MILLISECONDS);
    }catch(TimeoutException e){
        System.out.println("No response after one second");
        futureResult.cancel(true);
    }
    service.shutdown();
like image 55
Eugene Avatar answered Sep 30 '22 02:09

Eugene