Since Java 8, you can run a method asynchronously by using CompletableFuture.supplyAsync if you want to do something with the returning result or using CompletableFuture.runAsync if you don't
Apart from that, you can also use lambda statements, lambda expressions, and method references to provide the parameters of runAsync and supplyAsync methods
Let's walk through this tutorial to see the detail examples
runAsync has no return values while supplyAsync has
CompletableFuture.runAsyncaccepts aRunnablefunctional interface and return aCompletableFuture<Void>which doesn't have value
@Test
public void runAsync() throws ExecutionException, InterruptedException {
CompletableFuture c = CompletableFuture
.runAsync(() -> System.out.println("runAsync has no return values"));
assertThat(c.get()).isNull();
}
CompletableFuture.supplyAsyncaccepts aSupplier<U>functional interface and return aCompletableFuture<U>
@Test
public void supplyAsync() throws ExecutionException, InterruptedException {
CompletableFuture c = CompletableFuture
.supplyAsync(() -> "supplyAsync has return value");
assertThat(c.get()).isEqualTo("supplyAsync has return value");
}
runAsync and supplyAsync callbacks chain
- You can attach
thenRun*to therunAsynccallbacks chain
@Test
public void runAsyncWithCallbacks() throws ExecutionException, InterruptedException {
CompletableFuture c = CompletableFuture
.runAsync(() -> System.out.println("runAsync"))
.thenRunAsync(() -> System.out.println("callback"));
assertThat(c.get()).isNull();
}
- You can attach
thenApply*,thenCombine*,thenCompose*,thenAccept*andthenRun*to thesupplyAsynccallbacks chain
@Test
public void supplyAsyncWithCallbacks() throws ExecutionException, InterruptedException {
CompletableFuture c = CompletableFuture
.supplyAsync(() -> "supplyAsync")
.thenApplyAsync((s) -> s + " callback");
assertThat(c.get()).isEqualTo("supplyAsync callback");
}
Run runAsync and supplyAsync with an ExecutorService
Internally, CompletableFuture.runAsync(Runnable) and CompletableFuture.supplyAsync(Supplier) uses ForkJoinPool.commonPool() to execute
- You can provision a custom
ExecutortoCompletableFuture.runAsync(Runnable, Executor)as the following
@Test
public void runAsyncWithExecutor() throws ExecutionException, InterruptedException {
CompletableFuture c = CompletableFuture
.runAsync(() -> System.out.println("Run runAsync with an Executor"), executorService);
stop(executorService);
assertThat(c.get()).isNull();
}
- You can also provision a custom
ExecutortoCompletableFuture.supplyAsync(Supplier, Executor)
@Test
public void supplyAsyncWithExecutor() throws ExecutionException, InterruptedException {
CompletableFuture c = CompletableFuture
.supplyAsync(() -> "run supplyAsync with an Executor", executorService);
stop(executorService);
assertThat(c.get()).isEqualTo("run supplyAsync with an Executor");
}
Conclusion
In this tutorial, we explored the difference, how to use CompletableFuture.runAsync and CompletableFuture.supplyAsync to run a Runnable or Supplier method asynchronously. You can find the full source code as below