0

I made a function that is called allOfSequentialSupplierCombine(...) this function basically takes a linkedList of Suppliers of promises, and then it executes the promises one by one by chaining them recursively and then it builds an array of the results.

I've been debugging the code, I used Jprofiler o profile the memory and nothing abnormal, i've been reading on how promises are handled in memory, and how thread pools work

private static <T> CompletionStage<List<T>> allOfSequentialSupplierCombine(LinkedList<Supplier<CompletionStage<T>>> chain) {
        if (chain != null && !chain.isEmpty()) {
            Supplier<CompletionStage<T>> future = chain.pop();
            return future.get().thenCompose(r -> {
                return allOfSequentialSupplierCombine(chain).thenApply(list -> {
                    List<T> result = list;
                    if (list == null) {
                        list = new ArrayList<>();
                    }
                    list.add(0, r);
                    return list;
                });

            });
        }
        return CompletableFuture.completedFuture(null);
    }

The problem I am facing is that if I input more than 2000 suppliers, the function just stops without any error. I am expecting that maybe it creates too much threads in memory, resulting in the chain being broken.

Can anyone help me understand how the chained promises are stored in memory, does the jvm create as many threads as there are promises?

RobC
  • 22,977
  • 20
  • 73
  • 80
  • Check for the dad-lock by your profiller or simply use JConsole which is bundled with your jdk. In any case `LinkedList` is not thread safe, try to wrap it into `Collections.synchronizedList(chain)` or use another thread safe version of the stack, like [ConcurrentLinkedDeque](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentLinkedDeque.html) – Victor Gubin Aug 01 '19 at 09:36
  • BTW, it seams like`future.get()` waits for each other. Since you using a stack, try to implement this recursive algorithm without recursion. I.e. use `chain.push(supplier);... supplier = chain.pop(supplier);` – Victor Gubin Aug 01 '19 at 09:41
  • @VictorGubin thanks alot for the replies, so i basically tried using ConcurrentLinkedDeque and it doesn't solve it, at about 2000 recursive calls, everything stops. about the future.get(), yes that's the behaviour I want, I want the promises to run one by one and wait for others to finish before runing, that's why i called the method Sequential combine. but i'm looking in a non recursive solution, but this sis so weird i don't understand why this blocks at about 2000 iterations – BroPo Corp Aug 01 '19 at 10:08
  • Oh i used an exceptionally block and this is the error I got! my god there was an exception that's why it was blocking... java.util.concurrent.CompletionException: java.lang.BootstrapMethodError: call site initialization exception – BroPo Corp Aug 01 '19 at 10:15
  • Ok now i'm getting the infamous java.util.concurrent.CompletionException: java.lang.StackOverflowError. I thought that when i did a .get() on the future, it would wait before creating the other promises, guess i'm wrong, it seems taht i'm just spawning new threads – BroPo Corp Aug 01 '19 at 10:23
  • You're not calling `get()` on a `Future`, you're calling it on a `Supplier`. The latter interface is _non-blocking_. – Slaw Aug 01 '19 at 10:28
  • awsome, yeah so I used a blocking version, basically did a foreach on the chain, and i just iterate inside a supply async, and do a supplier.get().toCompletableFuture().join() on each supplier – BroPo Corp Aug 01 '19 at 12:03

0 Answers0