javacallablefuturetask

FutureTask get vs run, task never finishes


I am learning Callables and decided to make a very simple program. The problem is that the Thread is blocked when I call getFutureTask(); Thread.State: TIMED_WAITING (on object monitor)

Could you please tell me why is it so and why does my program work when I write futureTask.run() before futureTask.get(); I do understand that get() method waits and returns result. but can't understand what method run() does. I do appreciate your answers a lot!

   public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
       FutureTask futureTask = getFutureTask(1);
        System.out.println(futureTask.get());

    }


  public static FutureTask<Integer> getFutureTask(Integer i) {
        return new FutureTask<Integer>(() -> i*45);

    }

Solution

  • run vs get

    run is the method that actually starts the execution of the task. It is supposed to be called in a different thread, for example by an ExecutorService.

    get will not trigger execution, it just waits until the task is done, i.e. until run is finished. This obviously implies that you call run somehow before or from a different thread.


    ExecutorService and CompletableFuture

    FutureTask is not really supposed to be used directly by a user. It is more the type of class that is used behind the curtain in order to realize a nice async-API. More specifically, it is the base implementation for Future, as for example returned by ExecutorService when you spawn tasks with it.

    Instead you should look into ExecutorService

    ExecutorService service = Executors.newCachedThreadPool();
    ...
    Future<Integer> task = service.submit(() -> i * 45);
    ...
    Integer result = task.get();
    

    and CompletableFuture

    CompletableFuture<Integer> task = CompletableFuture.supplyAsync​(() -> i * 45);
    ...
    Integer result = task.get();
    

    for an easy to use interface to spawn async tasks.

    CompletableFutures have the advantage that you can also setup a pipeline of operations that are all executed asynchronously once the previous operation has finished. So for example:

    CompletableFuture<Void> task = CompletableFuture.supplyAsync(Foo::readSomeFile)
        .thenApplyAsync(Foo::validateData)
        .thenApplyAsync(Foo::compressData)
        .thenAcceptAsync(Foo::uploadData);