3

In my webapp supplyAsync method uses forkjoin pool in cloud linux environments but in local linux machines same code uses threads like thread-1 thread-2 with class web app class loader. Is there any configuration to change the default threadpool for completable futures.I want to get the local behaviour in cloud. Thread with a web app class loader. java version java 11, tomcat version 8.5.24.

CompletableFuture<Void> asyncFuture = future.thenAcceptAsync(t -> {
        if (!complete.getAndSet(true)) {
            try {
                completeAction.accept(t);
            } finally {
                synchronized (executor) {
                    K.shutdown();
                }
            }
        }
    });
    synchronized (executor) {
        if (!executor.isShutdown()) {
            executor.schedule(() -> {
                if (!complete.getAndSet(true)) {
                    try {
                        asyncFuture.cancel(false);
                        timeoutAction.run();
                    } finally {
                        executor.shutdown();
                    }
                }
            }, 200, 50);
        }
    }

enter image description here

srk
  • 4,857
  • 12
  • 65
  • 109
  • 1
    Have you tried passing an executor as the last parameter to `thenAcceptAsync`(https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html#thenAcceptAsync-java.util.function.Consumer-java.util.concurrent.Executor-) .. choose the appropriate on in either case .. ForkJoin or ThreadPoolExecutor respectively as needed. – Mr R Mar 19 '21 at 08:35

1 Answers1

2

Whether CompletableFuture uses a new thread per task or ForkJoinPool depends on the parallelism level of your system:

All async methods without an explicit Executor argument are performed using the ForkJoinPool.commonPool() (unless it does not support a parallelism level of at least two, in which case, a new Thread is created to run each task).

(cf. Javadoc).

The default parallelism level is one less than the number of processors, but you can change it to any value setting the system property java.util.concurrent.ForkJoinPool.common.parallelism (cf. ForkJoinPool).

However I would rather use a custom Executor, as in the comments to this and your previous question. The fact that newly created threads inherit the current thread context class loader, while the common pool doesn't, should be considered more as an implementation detail. Your code should work correctly in both cases.

Piotr P. Karwasz
  • 12,857
  • 3
  • 20
  • 43
  • 1
    Thank you I just cant identify why the same scenario and same code in same java and tomcat version behave differently. Only difference is the os in cloud environment. you have mentioned "All async methods without an explicit Executor argument are performed using the ForkJoinPool.commonPool()" but it is diffrernt in local environment. see image 1. yes I can use a custom executor but why this difference? Just want to find the reason behind the 2 cases – Hasintha Samith Randika Mar 19 '21 at 09:02
  • 1
    Your local machines must have a CPU count of 2 or less. While this configuration is uncommon for physical hardware these days, you can [use JVM options](https://stackoverflow.com/q/33723373/11748454) to achieve it. – Piotr P. Karwasz Mar 19 '21 at 09:09