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.runAsync
accepts aRunnable
functional 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.supplyAsync
accepts 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 therunAsync
callbacks 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 thesupplyAsync
callbacks 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
Executor
toCompletableFuture.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
Executor
toCompletableFuture.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