javafuturefuturetask

Async API using Future never completes


I try to make an API aysnchronous as:

Future<Integer> fASync(int x) {
        return new FutureTask(() -> {
            try {
                Thread.sleep(new Random().nextInt(1, 3) * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return x * x;
        });
    }

..then I try to use it:

Future<Integer> asyncCall = fASync(x);
asyncCall .get();

But this never completes and call just blocks.

Is this not correct way of making your API asynchronous?


Solution

  • You have declared a FutureTask but haven't actually run it so a call to asyncCall.get() will block forever.

    Here is your example with extra logging and adding a step to execute the task in a new ExecutorService.

    static FutureTask<Integer> fASync(int x) {
        System.out.println("fASync("+x+") called");
        return new FutureTask<>(() -> {
            System.out.println("fASync("+x+") FutureTask has started");
            try {
                Thread.sleep(new Random().nextInt(1, 3) * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("fASync("+x+") FutureTask has ended");
            return x * x;
        });
    }
    
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService exec = Executors.newFixedThreadPool(1);
        FutureTask<Integer> task = fASync(5);
        // MUST execute the task or task.get() will block forever
        exec.execute(task);
    
        System.out.println("task.get()="+task.get());
    
        exec.shutdown();
        exec.awaitTermination(1, TimeUnit.DAYS);
        System.out.println("ENDED");
    }
    

    If you enable the exec.execute(task); line it will print these messages and complete task.get(), instead of printing the first line only and no response from task.get():

    fASync(5) called
    fASync(5) FutureTask has started
    fASync(5) FutureTask has ended
    task.get()=25
    ENDED