java关于多线程异步中的坑
  LulQvNojilxV 2023年12月06日 41 0

相信很多小伙伴在工作学习中会遇到这类问题,调用别人的功能,但是不能批量,故多次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();
【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年12月06日 0

暂无评论

推荐阅读
  rvP2pqm8fEoB   2023年12月24日   34   0   0 ListJavaListJava
LulQvNojilxV