49

To run some stuff in parallel or asynchronously I can use either an ExecutorService: <T> Future<T> submit(Runnable task, T result); or the CompletableFuture Api:static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor); (Lets assume I use in both cases the same Executor)

Besides the return type Future vs. CompletableFuture are there any remarkable differences. Or When to use what?

And what are the differences if I use the CompletableFuture API with default Executor (the method without executor)?

Raedwald
  • 46,613
  • 43
  • 151
  • 237
dermoritz
  • 12,519
  • 25
  • 97
  • 185
  • 2
    `CompletableFuture` is newer, and has a lot more capabilities with a superior API. I recommend using it whenever possible. `Future` is woefully lacking. – John Kugelman Sep 13 '16 at 14:08
  • 2
    are there some facts behind? i don't want to refactor code because an api is just "newer" imho there could be executorservices that return CompetableFuture. – dermoritz Sep 13 '16 at 14:10
  • 7
    The fundamental problem with `Future` is that you have to waste threads waiting for them to complete. `CompletableFuture` flips the script and has the future invoke callbacks when it is finished. You don't need to have a thread blocked on `get()`. – John Kugelman Sep 13 '16 at 14:17
  • 3
    It's only a problem if you don't want them to wait. For instance, with Fork/Join the left side of the computation needs to wait for the right side to complete before returning. – John Vint Sep 13 '16 at 14:19
  • John can you probably make your last comment an answer - with little example? – dermoritz Sep 13 '16 at 16:23

3 Answers3

32

Besides the return type Future vs. CompletableFuture are there any remarkable differences. Or When to use what?

It's rather simple really. You use the Future when you want the executing thread to wait for async computation response. An example of this is with a parallel merge/sort. Sort left asynchronously, sort right synchronously, wait on left to complete (future.get()), merge results.

You use a CompleteableFuture when you want some action executed, with the result after completion, asynchronously from the executed thread. For instance: I want to do some computation asynchronously and when I compute, write the results to some system. The requesting thread may not need to wait on a result then.

You can mimic the above example in a single Future executable, but the CompletableFuture offers a more fluent interface with better error handling.

It really depends on what you want to do.

And what are the differences if i use the CompletableFutureApi with default Executor (the method without executor)?

It will delegate to ForkJoin.commonPool() which is a default size to the number of CPUs on your system. If you are doing something IO intensive (reading and writing to the file system) you should define the thread pool differently.

If it's CPU intensive, using the commonPool makes most sense.

Mithun Sasidharan
  • 20,572
  • 10
  • 34
  • 52
John Vint
  • 39,695
  • 7
  • 78
  • 108
  • thanks. so if i don't need the answer (in case of runnable) or i don't need the features of CompletableFuture, there is no difference? Could you probably giv short example what the main advantage is? – dermoritz Sep 13 '16 at 16:24
  • 5
    This answer doesn't make it clear why you'd want `Future`, ever. The advantage of `CompletableFuture` (async triggering of follow-on actions) is unique to it, but there is no advantage for `Future` - the "wait for result" is equally applicable to `CompletableFuture`. – BeeOnRope Dec 16 '16 at 22:21
  • Also `ForkJoin.commonPool()` is shared across the whole JVM, calculating `stream`s, and other tasks with no specific thread pool mentioned. – elirandav Mar 26 '18 at 13:06
  • 2
    I think @dermoritz is asking difference btw ExecutorService vs. CompletableFuture instead Future vs. CompletableFuture. – Steve Jul 19 '19 at 21:17
  • One main difference is what `@Chinmay` mentioned below: _none of them get executed unless we call .get method and during this time_, while `executorService.submit()/execute()` executes the logic once you do it. – Steve Jul 19 '19 at 21:30
  • An example code would have made this answer much clearer IMO. – aderchox Apr 18 '21 at 05:14
2

CompletableFuture has rich features like chaining multiple futures, combining the futures, executing some action after future is executed (both synchronously as well as asynchronously), etc.

However, CompletableFuture is no different than Future in terms of performance. Even when combine multiple instances of CompletableFuture (using .thenCombine and .join in the end), none of them get executed unless we call .get method and during this time, the invoking thread is blocked. I feel in terms of performance, this is not better than Future.

Please let me know if I am missing some aspect of performance here.

0

This clarified for me the difference between future an completable future a bit more: Difference between Future and Promise

CompletableFuture is more like a promise.

dermoritz
  • 12,519
  • 25
  • 97
  • 185