2

I have the following method using CompletableFuture like this:

public AClass aMethod() {

    CompletableFuture<SomeClassA> someClassAFuture =
        CompletableFuture.supplyAsync(() -> someMethodThatReturnsA());
    CompletableFuture<SomeClassB> someClassBFuture =
        CompletableFuture.supplyAsync(() -> someMethodThatReturnsB());
    CompletableFuture<SomeClassC> someClassCFuture =
        CompletableFuture.supplyAsync(() -> someMethodThatReturnsC());

    CompletableFuture.allOf(someClassAFuture, someClassBFuture, someClassCFuture).join();

    return new AClass(someClassAFuture.join(), someClassBFuture.join(), someClassCFuture.join());
}

This code has a deadlock problem when T threads simultaneously enter the method if there are less threads in the fork join pool than T * 3 (because none of the allOf calls can complete, and they will not return to the pool the currently taken threads).

The only way I have found to solve this was to limit the simultaneous threads inside the method (using Spring's @Async annotation with a thread executor) or increasing the threads in the fork join pool.

I would like some better solution where I can completely forgot about the thread pool size. How can I rewrite this using Reactor or Akka?

Jeffrey Chung
  • 19,319
  • 8
  • 34
  • 54
italktothewind
  • 1,950
  • 2
  • 28
  • 55

1 Answers1

0

The implementation in Akka futures would be something like (completely untested):

Future< SomeClassA > f1 = future(() -> someMethodThatReturnsA(), system.dispatcher());
Future< SomeClassB > f2 = future(() -> someMethodThatReturnsB(), system.dispatcher());
Future< SomeClassC > f3 = future(() -> someMethodThatReturnsC(), system.dispatcher());

List<Future<Object>> futures = Arrays.asList(f1, f2, f3);

return sequence(futures).map((results) ->  new AClass(results.get(0),results.get(1),results.get(2)));

Some extra work could be required to parse the futures result before create AClass. Note that you are returning a Future< AClass > now in the aMethod

Though, the problem with your code is that it's blocking. Did you try to join all the CompletableFutures using thenApply and thenCompose to return a CompletableFuture<AClass>?

RoberMP
  • 1,306
  • 11
  • 22
  • Hi! Are you sure that this code has not any deadlock? It looks very similar to my previous code. – italktothewind May 02 '18 at 16:00
  • I'm very sure than it isn't since we are not blocking anywhere. The reason of the deadlock is (probably) this line: `CompletableFuture.allOf(someClassAFuture, someClassBFuture, someClassCFuture).join();` which is blocking until the 3 tasks complete. At some point we can run out of threads to accomplish the 3 tasks so we get a thread starvation problem. – RoberMP May 03 '18 at 10:16