Context: I've read this SO thread discussing the differences between CompletableFuture and Thread.
But I'm trying to understand when should I use new Thread() instead of runAsync().
I understand that runAsyn() is more efficient for short/one-time parallel task because my program might avoid the overhead of creating a brand new thread, but should I also consider it for long running operations?
What are the factors that I should be aware before considering to use one over the other?
Thanks everyone.
The difference between using the low-level concurrency APIs (such as Thread) and others is not just about the kind of work that you want to get done, it's also about the programming model and also how easy they make it to configure the environment in which the task runs.
In general, it is advisable to use higher-level APIs, such as CompletableFuture
instead of directly using Thread
s.
I understand that runAsyn() is more efficient for short/one-time parallel task
Well, maybe, assuming you call runAsync
, counting on it to use the fork-join pool. The runAsync
method is overloaded with a method that allows one to specify the java.util.concurrent.Executor
with which the asynchronous task is executed.
Using an ExecutorService
for more control over the thread pool and using CompletableFuture.runAsync
or CompletableFuture.supplyAsync
with a specified executor service (or not) are both generally preferred to creating and running a Thread
object directly.
There's nothing particularly for or against using the CompletableFuture API for long-running tasks. But the choice one makes to use Thread
s has other implications as well, among which:
CompletableFuture
gives a better API for programming reactively, without forcing us to write explicit synchronization code. (we don't get this when using threads directly)Future
interface (which is implemented by CompletableFuture
) gives other additional, obvious advantages.So, in short: you can (and probably should, if the alternative being considered is the Thread
API) use the CompletableFuture
API for your long-running tasks. To better control thread pools, you can combine it with executor services.
The main difference is CompletableFuture
run your task by default on the ForkJoinPool.commonPool
. But if you create your own thread and start it will execute as a single thread, not on a Thread pool. Also if you want to execute some task in a sequence but asynchronously
. Then you can do like below.
CompletableFuture.runAsync(() -> {
System.out.println("On first task");
System.out.println("Thread : " + Thread.currentThread());
}).thenRun(() -> {
System.out.println("On second task");
});
Output:
On first task
Thread : Thread[ForkJoinPool.commonPool-worker-1,5,main]
On second task
If you run the above code you can see that which pool CompletableFuture
is using.
Note: Threads is Daemon in
ForkJoinPool.commonPool
.
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