java关于多线程异步中的坑

        相信很多小伙伴在工作学习中会遇到这类问题,调用别人的功能,但是不能批量,故多次feign接口远程调用,导致接口响应时间过长。

        这时候就会考虑到我们的多线程来解决这类问题了,使用多线程那么首先肯定是要创建线程池了

下面是自定义线程池方法,根据CPU动态设置核心线程,最大线程数以及队列数量。

@Configuration
@EnableAsync
@AutoConfigureAfter(BifrostProperties.class)
@AllArgsConstructor
public class BFPExecutorConfig {
    private static final Logger logger = LoggerFactory.getLogger(com.szjz.cloud.bifrost.boot.base.core.thread.ExecutorConfig.class);
    private BifrostProperties bifrostProperties;
    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    @Bean("BfpAsyncPool")
    public Executor threadPoolTaskExecutor() {
        logger.info("start asyncServiceExecutor");
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setKeepAliveSeconds(60);
        //配置核心线程数
        executor.setCorePoolSize(CPU_COUNT+1);
        //配置最大线程数
        executor.setMaxPoolSize(CPU_COUNT*2+1);
        //配置队列大小
        executor.setQueueCapacity((CPU_COUNT*2+1)*100);
        //配置线程池中的线程的名称前缀
        executor.setThreadNamePrefix(bifrostProperties.getThreadPool().getThreadNamePrefix());
        // rejection-policy:当pool已经达到max size的时候,如何处理新任务
        // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //执行初始化
        executor.initialize();
        // 额外的处理,生成修饰了的对象executorService
        // TtlExecutors.getTtlExecutorService((ExecutorService) executor);
        return executor;
    }
}

自定义线程池之后就来到今天的主题,下面map是执行feign接口需要用到的参数,hashmap用来存储异步方法的返回值,executor是我们自定义的线程池,当我们在使用这个多线程异步方法的时候要注意当我们进入异步方法后子线程无法获取上下文信息,但是主线程不影响,会导致子线程内获取token失败,从而导致接口调用失败。

Map<String, Object> map = new HashMap<>();
            map.put("year", t.getYear());

            ConcurrentHashMap<String, List<Map<String, Object>>> hashMap = new ConcurrentHashMap<>();
            Executor executor = executorConfig.threadPoolTaskExecutor();
            List<CompletableFuture> futures = new ArrayList<>();
            for (String id : dsIds) {
                final String currId = id;
                CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                    // 调用查询方法,返回List<Map<String, Object>>
                    try {
                        List<Map<String, Object>> resultList = dataSetService.getListMapByDsId(currId, map);
                        hashMap.put(currId, resultList);
                    } catch (Exception e) {
                        throw new BizException(BaseCode.ERROR, "");
                    }
                }, executor).exceptionally(e -> {
                    throw new BizException(BaseCode.ERROR,  currId);
                });
                futures.add(future);
            }
            CompletableFuture<Void> allFutures = null;
            allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()]));
            allFutures.join();

正确的方式应该是这样:每个地方获取上下文方式不同,小编就用注释标注添加位置了,

最后最最最最重要的一件事:感谢各位老板的观看!

Map<String, Object> map = new HashMap<>();
            map.put("year", t.getYear());
// 在for循环外获取上下文信息 并在异步方法内赋值给子线程上下文信息
            ConcurrentHashMap<String, List<Map<String, Object>>> hashMap = new ConcurrentHashMap<>();
            Executor executor = executorConfig.threadPoolTaskExecutor();
            List<CompletableFuture> futures = new ArrayList<>();
            for (String id : dsIds) {
                final String currId = id;
                CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                    // 调用查询方法,返回List<Map<String, Object>>
                    try {
                // 在这里赋值上下文信息
                        List<Map<String, Object>> resultList = dataSetService.getListMapByDsId(currId, map);
                        hashMap.put(currId, resultList);
                    } catch (Exception e) {
                        throw new BizException(BaseCode.ERROR, "");
                    }
                }, executor).exceptionally(e -> {
                    throw new BizException(BaseCode.ERROR,  currId);
                });
                futures.add(future);
            }
            CompletableFuture<Void> allFutures = null;
            allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()]));
            allFutures.join();

  • 12
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值