CompletableFuture was a new addition in Java 8. It provides a future that can be explicitly completed. We can then respond to the completion of the future using a variety of callbacks to transform and respond to our data in a variety of ways.
Here's a basic example of a CompletableFuture that waits for 5 seconds before emitting a String value:
CompletableFuture.supplyAsync {
Thread.sleep(5000)
"Future is done"
}
We can retrieve this value in a blocking fashion like so:
val returnedValue = future.get()
It's more likely that we'll want to run the code in an asynchronous manner and then respond once the value is returned. The following snippet shows one way in which we could do this, that is, by using the thenAccept() method:
CompletableFuture.supplyAsync {
Thread.sleep(5000)
"Future is done"
}.thenAccept {
println(it)
}
The thenAccept() method is a terminal method that allows us to respond to the completion of this future. When using thenAccept() to respond to completion, we have access to the final value. However, if we don't require the final value, we could use thenRun() to run an arbitrary code in response to completion:
CompletableFuture.supplyAsync {
Thread.sleep(5000)
"Future is done"
}.thenRun {
println("The future completed")
}
When using CompletableFuture, we can also transform our data stream using a variety of operators. In the following code snippet, we can map the returned String to a new String value using thenApply():
CompletableFuture.supplyAsync {
Thread.sleep(5000)
"Future is done"
}.thenApply {
"The supplied value was: $it"
}.thenAccept {
println(it)
}
CompletableFuture is a useful API for composing, transforming, and responding to asynchronous operations if you're targeting Java 8 or newer.