2

I'm having a very weird problem with CompletableFuture

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {

    final static ExecutorService executor = Executors.newCachedThreadPool();

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            final CompletableFuture withoutExecutor = doSomethingOne(i);
//      final CompletableFuture withExecutor = doSomethingTwo(i);
        }
    }

    private static CompletableFuture doSomethingOne(final int i) {
        return CompletableFuture.runAsync(() -> {
            System.out.println("Without Executor " + i);
        });
    }

    private static CompletableFuture doSomethingTwo(final int i) {
        return CompletableFuture.runAsync(() -> {
            System.out.println("With Executor " + i);
        }, executor);
    }
}

When main is executed, it doesn't print anything (the withoutExecutor CompletableFuture doesn't even get executed). But when I uncomment the withExecutor, both CompletableFutures work as expected. What am I missing?

I have similar problem in my personal project, but the overall idea is the same. I am currently using an executor with my CompletableFutures in the project, and they only run for a certain amount of time, then they stop running completely (Even debugger doesn't hit a breakpoint within CompletableFuture). I need an async background task, waiting is not an option since CompletableFuture is triggered via a REST API in my project, and I have to return result of storing the Story as soon as possible.

  • Speculating, but possibly related to `main` ending (so the whole program ends) before the `CompleteFuture` has a chance to run. It might also depends on if the thread pool creates the workers as a daemon or non-daemon thread. – Andrew S Apr 20 '23 at 16:41
  • The duplicate addresses the _code_ in your question. I'm not sure if it will address the problem in your real project. Let me know one way or the other, please. – Slaw Apr 20 '23 at 16:45

1 Answers1

2

Try this code

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Consumer;

public class Main {

    private static final ExecutorService executor = Executors.newCachedThreadPool();

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            Consumer<Integer> consumer = result -> System.out.println("Result: " + result);
            doSomething(i)
                    .thenAcceptAsync(consumer, executor);
        }
        System.out.println("Main thread is not blocked");
    }

    private static CompletableFuture<Integer> doSomething(final int i) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(2500);
            } catch (InterruptedException interruptedException) {
                interruptedException.printStackTrace();
            }
            return i * 3;
        }, executor);
    }
}
Zufar Sunagatov
  • 668
  • 1
  • 6
  • 16