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:
- The
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)
- The
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.