Search code examples
javatomcatclassloadercompletable-future

Thread of supplyAsync in Java completable future uses different threads in different environments


In my web app a 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


Solution

  • 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.