Asynchronous non-blocking task with CompletableFutures

Great question. Yes a CompleteableFuture is perfect for your needs! Lets investigate further the functionality of the class.

A CompleteableFuture is a wrapper for the Future class and allows for executing in parallel. Lets take a look at an example from this article.

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    try {
        TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
        throw new IllegalStateException(e);
    }
    return "Result of the asynchronous computation";
});

In the above example, the program will start the CompletableFuture asynchronously and will have the new thread sleep in the background. If we add .thenApply() seen below:

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    try {
        TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
        throw new IllegalStateException(e);
    }
    return "Result of the asynchronous computation";
}).thenApply(result -> {
   System.out.println(result);
   return "Result of the then apply";
});

The application will execute just as we discussed before, but once it completes (non-exceptionally) the current thread running the supplyAsync will execute the print statement.

Note, if a synchronous transformation is added to a future after it has finished execution, the calling thread will perform the transformation. As we see below:

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    try {
        TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
        throw new IllegalStateException(e);
    }
    return "Result of the asynchronous computation";
});
// Long calculations that allows the future above to finish
future.thenApply(result -> {
   System.out.println(result);
   return "Result of the then apply";
});

the thenApply will run on the thread that runs future.thenApply(...), not the thread spawned to run the supplyAsync in the background.