What is the advantage of passing code directly to thread vs using CompletableFuture instead?
Thread thread = new Thread(() -> {do something}); thread.start();
VS
CompletableFuture<Void> cf1 = CompletableFuture.runAsync(() -> {do something});
Yes! CompletableFuture executes these tasks in a thread obtained from the global ForkJoinPool. commonPool(). But hey, you can also create a Thread Pool and pass it to runAsync() and supplyAsync() methods to let them execute their tasks in a thread obtained from your thread pool.
CompletableFuture is inherently thread-safe The results of a write by one thread are guaranteed to be visible to a read by another thread only if the write operation happens-before the read operation.
The ExecutorService executes a task and updates the result in the Future. A CompletableFuture introduced later in Java 8 implements the Future interface. So CompletableFuture contains all the functionalities provided by the Future interface. The CompletableFuture allows you to chain tasks together.
The Future interface doesn't provide a lot of features, we need to get the result of asynchronous computation using the get() method, which is blocked, so there is no scope to run multiple dependent tasks in a non-blocking fashion whereas CompleteFuture class can provide the functionality to chain multiple dependent ...
CompletableFuture.runAsync(...)
runs the Runnable in the forkJoin-Pool which is managed, while new Thread()
creates a new thread which you have to manage.
What does "is managed" mean, it's pre-allocated and the threads are shared in the JVM. When the runnable is completed, the thread can be reused for other runnables. This makes better usage of resources, especially as thread instantiation is an expensive operation - not only the object, but also some extra non-heap memory - the thread stack - has to be allocated.
@Gerald Mücke already mentioned the important difference:
CompletableFuture.runAsync(...) runs the Runnable in the forkJoin-Pool which is managed, while new Thread() creates a new thread which you have to manage.
CompletableFuture will use threads managed by a ThreadPool (default or customized).
However, I think the following two points are also should be considered.
CompletableFuture has so many easily understandable methods to chain different asynchronous computations together, making it much easier to introduce asynchrony than directly using Thread.
CompletableFuture[] futures = IntStream.rangeClosed(0, LEN).boxed() .map(i -> CompletableFuture.supplyAsync(() -> runStage1(i), EXECUTOR_SERVICE)) .map(future -> future.thenCompose(i -> CompletableFuture.supplyAsync(() -> runStage2(i), EXECUTOR_SERVICE))) .toArray(size -> new CompletableFuture[size]); CompletableFuture.allOf(futures).join();
You should never forget to handle exceptions; with CompletableFuture, you can directly handle them like this:
completableFuture.handle((s, e) -> e.toString()).join()
or take advantage of them this way to interrupt the computation:
completableFuture.completeExceptionally(new RuntimeException("Calculation failed!"));
while you will easily encounter some serious problems using Thread.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With