javafutureexecutorservicejava.util.concurrentfuturetask

Java ExecutorsService submit a FutureTask get on Future returns null


I have this snippet.

    final ExecutorService executor = Executors.newFixedThreadPool(3);
    final Runnable runnable = ()->{System.out.println("Inside runnable run method");};
    final Callable<String>callable = ()->{System.out.println("Inside callable call method");return "callable";};
    final FutureTask<String> futureTask = new FutureTask<>(()->{System.out.println("CallableInFutureTask");},"JOHN");
    final FutureTask f1 = (FutureTask)executor.submit(callable);
    final FutureTask f2 = (FutureTask)executor.submit(futureTask);
    final FutureTask f3 = (FutureTask)executor.submit(runnable);
    System.out.println("f1 = " + f1+" "+f1.isDone()+" "+f1.get());
    System.out.println("FutureTask Reference Object: "+futureTask.isDone()+" "+futureTask.get());
    System.out.println("f2 = "+f2.isDone()+" "+f2.get());
    System.out.println("f3 = " + f3+" "+f3.isDone()+" "+f3.get());        
    executor.shutdown();

The f1 and f3 Future variables is returning the correct values of its get method but the FutureTask past it to the Executors the f2 is returning null why is this? Even the futureTask reference is returning the correct value "JOHN" for the get method but why is this? Maybe because i am passing a FutureTask? I dont get it.

I just thought that f2 and futureTask references would return the same value. Sorry if this question is simple thanks a lot.


Solution

  • When you submit a FutureTask to a ExecutorService it is treated as a Runnable so the the Future you get from the submit method would have the value null as the Runnable instances don't return any result.

    Since the FutureTask implements the Runnable interface this method of the ExecutorService is called submit(Runnable task) so the Runnable you are wrapping in the FutureTask constructor is actually submitted to the ExecutorService and hence you get null on the invocation of f2.get().

    But when you are calling the get() on the FutureTask reference you are then getting back the value you supplied as the second parameter once the Runnable has completed its execution (when you submitted the task earlier in the ExecutorService).

    You can also verify this by not submitting the futureTask in the ExecutorService, then if you try to invoke get on the futureTask variable the get call will block indefinitely as the Runnable has not been executed.

     // Returning "JOHN" when the supplied Runnable is completed execution.
     System.out.println("FutureTask Reference Object: "+futureTask.isDone()+" "+futureTask.get());
    

    This is as per the docs:

    Creates a FutureTask that will, upon running, execute the given Runnable, and arrange that get will return the given result on successful completion.