2

I am trying to understand the CompletableFuture interface in Java 8. My current code is:

CompletableFuture.supplyAsync(() -> wachtwoordBijwerken(gebruikersnaam, wachtwoord))
    .thenAccept(this::saveOrUpdateGebruiker)
    .exceptionally(e ->
    {
        log.error("Fout bij het bijwerken van wachtwoord voor gebruiker: " + gebruikersnaam, e);
        return null;
    });

I expected the call saveOrUpdateGebruiker() to run in the main thread after the async call in the newly created thread is completed. However, the call is still in another thread, which causes problems in the underlying hibernate implementation.

Is there a way to use CompletableFuture for a non blocking async call, and still being able to use the result in my current thread?

Cloud
  • 458
  • 1
  • 13
  • 34

3 Answers3

3

Not automatically no. When performing operations as provided by CompletableFuture with supplyAsync, thenAccept etc. they're all performed by a thread in the threadpool. That allows you to do "fire and forget" operations and continuing work in the main thread as you see fit.

If you want to perform work in your current thread after the CompletableFuture has finished, you need to wait and check for its completion by using isDone() and/or get() methods.

However if you do this, then there is no advantage of using CompletableFuture over a normal Future (e.g. FutureTask).

Kayaman
  • 72,141
  • 5
  • 83
  • 121
1

Using CompletableFuture is an overkill for your scenario. CompletableFuture is non-blocking in its design and when the job is done, you can collect its results by using join() or polling isDone() method and then do synchronous operation. If you have only one process keep sending tasks to dedicated ThreadPool, there's no advantage of using CompletableFuture than CompletionService or just ExecutorService. I wrote a simple blog on one scenario where CompletableFuture is a good fit compared to traditional Threadpool:https://medium.com/@zhongzhongzhong/beauty-of-completablefuture-and-where-should-you-use-it-6ac65b7bfbe

Zhong Hu
  • 272
  • 2
  • 5
0

You can use the method thenAcceptAsync(Runnable, Executor) which uses the executor you passed in parameter to execute the callback, which it can be eventually the same that the one you have for the caller

Like that, you can control the thread/executor used for executing your callback code

See also : This related Stackoverflow question

Prim
  • 2,880
  • 2
  • 15
  • 29
  • 1
    There's now two conflicting answers here. Maybe you should modify your answer a bit, since the answer is not "Yes", the answer is "No, you can't run it in the **current thread**". Otherwise the answer is good. – Kayaman Jul 03 '17 at 14:20
  • Unfortunately this is not correct. Even with executor tricks you can't get the code to run on the same thread where you called `supplyAsync` from. The related question describes an executor that will run on the current thread, but this question is about the current thread, a thread in a pool (that runs `supplyAsync`) and finally running again in current thread. If the described executor is supplied, it will be the pooled thread that runs it (since it is the "current thread" at that point). – Kayaman Jul 04 '17 at 15:09