使用CompletableFuture进行多线程时未指定线程池踩坑ClassNotFoundException

问题描述:

CompletableFuture广泛应用于快速构建异步线程调用,在使用过程中,不当地使用可能会导致属性注入的service或者Mapper持久层,ClassLoader未能正常获取类,导致ClassNotFindException,该问题的发现也是在部分代码的书写中,有部分地方忘记配置线程池,从而导致了问题的出现。

public void doTask(Request request){

        AService bean = SpringUtils.getBean(AService.class);

        CompletableFuture.runAsync(() -> {

            bean.doSomething();
            DbEntity dbSubtask = dbEntityMapper.selectOne(Wrappers.lambdaQuery(DbEntity.class)
                .eq(DbEntity ::getId, request.getId())
                .eq(DbEntity ::getName, request.getName()));

            return null;
        }).exceptionally(throwable -> {
            Optional.ofNullable(throwable).ifPresent(item -> {
                log.error("translateEpisode 发生错误:", item);
            });
        });

}
临时解决方案及思路:

CompletableFuture在没有指定工作线程池的情况下,会使用默认提供的forkJoin线程池,在Tomcat容器中,tomcat没有直接使用jdk8原生的ForkjoinPool,而是定制了自己的SafeForkJoinWorkerThread且将从线程的contextClassLoader设置为null导致的,以此来解决java8的默认的ForkJoinPool内存泄漏问题。如果在ForkJoinPool里面使用LambdaWrapper出现ClassNotFoundException就会是个必现问题;

我当时遇到报错信息是在一个service方法中,通过在CompletableFuture外getBean的方式,临时解决了这个问题;

最终解决思路:

通过查阅相关的issue,通过指定worker线程池,可以避免这一情况的发生,也可以通过这种方式进行处理;

线程池的示例代码:

    @Bean(name = "workerExecutor")
    public Executor executor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(maxPoolSize);
        executor.setQueueCapacity(queueCapacity);
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }

这个问题其实也可以作为,为什么在使用CompletableFuture时建议指定执行线程池的原因之一;

参考issue:

mybatisPlus-issue

腾讯云问题分析

https://cloud.tencent.com/developer/article/1511111

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值