Java编码指南:慎用CompletableFuture中不带线程池参数的那些方法

2023-06-19 16:50:15 浏览数 (1)


CompletableFuture提供异步执行的方法总是成对的


例如:

代码语言:javascript复制
java.util.concurrent.CompletableFuture#supplyAsync
代码语言:javascript复制
    /**
     * Returns a new CompletableFuture that is asynchronously completed
     * by a task running in the {@link ForkJoinPool#commonPool()} with
     * the value obtained by calling the given Supplier.
     *
     * @param supplier a function returning the value to be used
     * to complete the returned CompletableFuture
     * @param <U> the function's return type
     * @return the new CompletableFuture
     */
    public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {
        return asyncSupplyStage(ASYNC_POOL, supplier);
    }

    /**
     * Returns a new CompletableFuture that is asynchronously completed
     * by a task running in the given executor with the value obtained
     * by calling the given Supplier.
     *
     * @param supplier a function returning the value to be used
     * to complete the returned CompletableFuture
     * @param executor the executor to use for asynchronous execution
     * @param <U> the function's return type
     * @return the new CompletableFuture
     */
    public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,
                                                       Executor executor) {
        return asyncSupplyStage(screenExecutor(executor), supplier);
    }

两个方法的重要区别是:异步运行的线程池是显示提供的,还是使用默认的

ASYNC_POOL:

代码语言:javascript复制
/**
     * Default executor -- ForkJoinPool.commonPool() unless it cannot
     * support parallelism.
     */
    private static final Executor ASYNC_POOL = USE_COMMON_POOL ?
        ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();

CompletableFuture提供异步执行的方法,强制使用显示提供线程池


why?

1、默认提供的线程池,会使得相关的异步执行都共用一个线程池,不合理;而且不能相互隔离业务的执行;线程池的参数也不能改变

2、默认提供的线程池,在微服务spring cloud环境中,会丢失链路信息,导致链路traceId丢失;对于排查问题增加困难;

We provide LazyTraceExecutor, TraceableExecutorService, and TraceableScheduledExecutorService. Those implementations create spans each time a new task is submitted, invoked, or scheduled.‍ https://docs.spring.io/spring-cloud-sleuth/docs/current/reference/html/integrations.html#sleuth-async-executor-service-integration

3、压测链路信息丢失,因为压测链路信息存放在链路信息上下文中;

https://docs.spring.io/spring-cloud-sleuth/docs/current/reference/html/project-features.html#features-baggage https://docs.spring.io/spring-cloud-sleuth/docs/current/reference/html/project-features.html#features-baggage

4、如果默认线程池为ForkJoinPool,使得线程上下文类加载器ContextClassLoader固定为SystemClassLoader,容易导致类加载失败

小结


CompletableFuture提供异步执行的方法,强制使用显示提供线程池,能避免上述提到的一些问题。


0 人点赞