java completable future中supplyAsync的线程在不同环境下使用不同的线程

问题描述

在我的 webapp supplyAsync 方法中,在云 linux 环境中使用 forkjoin 池,但在本地 linux 机器中,相同的代码使用线程,如 thread-1 thread-2 和类 web 应用程序类加载器。是否有任何配置可以更改可完成期货的认线程池。我想在云中获取本地行为。线程与 Web 应用程序类加载器。 java版本java 11,tomcat版本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

enter image description here

解决方法

CompletableFuture 为每个任务使用一个新线程还是 ForkJoinPool 取决于您系统的并行度:

所有没有显式 Executor 参数的异步方法都使用 ForkJoinPool.commonPool() 执行(除非它不支持至少两个并行级别,在这种情况下,会创建一个新线程来运行每个任务)。

(参见Javadoc)。

默认并行级别比处理器数量少 1,但您可以通过设置系统属性 java.util.concurrent.ForkJoinPool.common.parallelism(参见 ForkJoinPool)将其更改为任何值。

不过,我更愿意使用自定义 Executor,如对此和您的 previous question 的评论中所述。新创建的线程继承当前线程上下文类加载器,而公共池没有,这一事实应该更多地被视为实现细节。您的代码应该在这两种情况下都能正常工作。