多线程代码示例

dubbo异步多线程调用

    public List<LotteryCategoryVo> selectChildrenAll(List<String> pids) {
        long start = System.currentTimeMillis();
        log.info("selectChildrenAll start:{}",start);
        List<Category> categories = null;
        AbstractAsyncBatchInvokeUtils<List<Category>, String> abstractAsyncBatchInvokeUtils = new AbstractAsyncBatchInvokeUtils<List<Category>, String>() {
            @Override
            public void invoke(String pid) {
                categoryService.selectChildren(Long.valueOf(pid));
            }
        };
        try {
        Iterable<List<String>> partition = Iterables.partition(pids, 10);
            for (List<String> e : partition) {
                List<List<Category>> list = abstractAsyncBatchInvokeUtils.asyncBatchInvoke(e, 100, 1);
                for (List<Category> categoryList : list) {
                    categories.addAll(categoryList);
                }
            }
        } catch (Exception e) {
            log.error("导出查询会员信息失败,错误信息为:{}", e.getMessage(), e);
            throw new GenericBusinessException("导出查询会员信息失败");
        }
        List<LotteryCategoryVo> result = convertCategoryVo(categories);
        log.info("selectChildrenAll end:{} end-start:{} ms",System.currentTimeMillis(),System.currentTimeMillis()-start);
        return result;
    }
/**
 * dubbo批量异步接口,调用者实现invoke方法,限制50条,超长的调用者自行分页
 *
 * todo 该方法存在优化点:需要依赖dubbo配置文件async=true ,如果能在RpcContext中修改RpcInvocation参数为异步可以在这里自定义参数将会摆脱配置文件的依赖
 * @author:zxd
 * @date: 9/3/21
 * @time: 4:26 PM
 */
@Slf4j
public abstract class AbstractAsyncBatchInvokeUtils<T, V> {

    /**
     * 策略:某异步线程异常,方法停止,向上抛出
     */
    public static final int UN_CATCH_EXCEPTION_HANDLER_STRATEGY = 0;

    /**
     * 策略:吞掉某异步线程异常
     */
    public static final int CATCH_EXCEPTION_HANDLER_STRATEGY = 1;

    /**
     * 入参params的长度限制,批量执行,
     */
    public static final int PARAM_SIZE_LIMIT = 50;


    /**
     * 基于dubbo消费者线程池异步消费方法的批量执行器,方法内是异步,对外返回的结果是同步的
     * 注意:dubbo方法的配置文件需要async=true
     * @param params params 参数集合
     * @param singleWaitTime 单线程等待时间,单位毫秒,为0则表示使用dubbo.xml设置的方法调用时间
     * @param handlerStrategyStatus 异常处理策略 NO_CATCH_EXCEPTION_HANDLER_STRATEGY 或者 CATCH_EXCEPTION_HANDLER_STRATEGY
     * @return List<T> 直接返回结果
     */
    public List<T> asyncBatchInvoke(Collection<V> params, long singleWaitTime, int handlerStrategyStatus)
            throws InterruptedException, ExecutionException, TimeoutException {
        if (CollectionUtils.isEmpty(params) || params.size() > PARAM_SIZE_LIMIT) {
            throw new BadParameterException("参数异常");
        }
        List<Future<T>> futureList = batchInvoke(params);
        List<T> list = Lists.newArrayList();
        for (Future<T> future : futureList) {
            // 某线程异常直接吞掉
            if (handlerStrategyStatus == CATCH_EXCEPTION_HANDLER_STRATEGY) {
                T t = null;
                Object[]  arguments = null;
                try {
                    FutureAdapter future1 = (FutureAdapter) future;
                    DefaultFuture defaultFuture = (DefaultFuture)future1.getFuture();
                    Request request = defaultFuture.getRequest();
                    RpcInvocation data = (RpcInvocation)request.getData();
                    arguments = data.getArguments();
                    if (singleWaitTime <= 0L){
                        t = future.get();
                    }else {
                        t = future.get(singleWaitTime, TimeUnit.MILLISECONDS);
                    }
                } catch (Exception e) {
                    if (log.isInfoEnabled()) {
                        log.info("AbstractAsyncBatchInvokeUtils.asyncBatchInvoke 批量方法执行报错," +
                                        "失败线程参数arguments={},singleWaitTime={},handlerStrategyStatus={}",
                                JSON.toJSONString(arguments), singleWaitTime, handlerStrategyStatus, e);
                    }
                    Thread.currentThread().interrupt();
                }
                if (t != null) {
                    list.add(t);
                }
            } else if (handlerStrategyStatus == UN_CATCH_EXCEPTION_HANDLER_STRATEGY) {
                // 不吞掉异常
                T t = future.get(singleWaitTime, TimeUnit.MILLISECONDS);
                if (t != null) {
                    list.add(t);
                }
            }
        }
        log.info("AbstractAsyncBatchInvokeUtils.asyncBatchInvoke 结果返回result={}", JSON.toJSONString(list));
        return list;
    }

    /**
     * 具体执行的方法,调用者实现该方法的具体业务逻辑
     *
     * @param v 参数
     */
    public abstract void invoke(V v);

    /**
     * 基于dubbo消费者线程池异步消费方法的批量执行器,返回future类型结果,为异步的方法,调用者自行从future中拿结果
     *
     * @param params params 参数集合
     * @return  List<Future<T>> 返回future的集合结果
     */
    public List<Future<T>> asyncBatchInvoke(Collection<V> params) {
        if (CollectionUtils.isEmpty(params) || params.size() > PARAM_SIZE_LIMIT) {
            throw new BadParameterException("参数异常");
        }
        List<Future<T>> futureList = batchInvoke(params);
        return futureList;
    }

    /**
     * 批量批异步执行目标方法
     * @param params
     * @return 返回 future,使用者可以根据实际逻辑,先做其他事情再获取future中的结果,做到真正的异步
     * @throws Exception
     */
    private List<Future<T>> batchInvoke(Collection<V> params) {

        List<Future<T>> futureList = Lists.newArrayList();
        for (V param : params) {
            invoke(param);
            Future<T> future = RpcContext.getContext().getFuture();
            futureList.add(future);
        }
        return futureList;
    }



}

@Configuration
@EnableAsync
@SuppressWarnings("all")
public class ThreadPoolConfiguration {
    @Bean("lotteryCategoryTaskExecutor")
    public ThreadPoolTaskExecutor lotteryCategoryTaskExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setCorePoolSize(10);
        threadPoolTaskExecutor.setMaxPoolSize(20);
        threadPoolTaskExecutor.setKeepAliveSeconds(200);
        threadPoolTaskExecutor.setQueueCapacity(100);
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        return threadPoolTaskExecutor;
    }
}

同步多线程调用:

    @Override
    public List<LotteryCategoryVo> selectChildrenAll(List<String> pids) {
        List<LotteryCategoryVo> result = new ArrayList<>();
        List<Future<List<LotteryCategoryVo>>> futureList = new ArrayList<>();
        for (String pid : pids) {
            Future<List<LotteryCategoryVo>> future = selectChildrenAllTaskExecutor.submit(CallableWrapper.of(() -> this.selectChildren(pid)));
            futureList.add(future);
        }

        futureList.stream().forEach((task) -> {
            try {
                List<LotteryCategoryVo> lotteryCategoryVos = task.get();
                result.addAll(lotteryCategoryVos);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        });
        return result;
    }

    @Bean("selectChildrenAllTaskExecutor")
    public ThreadPoolTaskExecutor selectChildrenAllTaskExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setCorePoolSize(10);
        threadPoolTaskExecutor.setKeepAliveSeconds(200);
        threadPoolTaskExecutor.setMaxPoolSize(20);
        threadPoolTaskExecutor.setQueueCapacity(500);
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        return threadPoolTaskExecutor;
    }
    public LotteryCategoryQueryVo getCategory(String activityCode) {
        log.info("查询分类耗时:t1:{}", System.currentTimeMillis());

        LotteryCategoryRes lotteryCategoryRes = lotteryActivityService.queryCategory(activityCode);
        if (ObjectUtils.isEmpty(lotteryCategoryRes)) {
            return LotteryCategoryQueryVo.builder().isSelect(false).build();
        }

        List<String> levelOneSelect = lotteryCategoryRes.getLotteryCategory().getLevelOne();
        List<String> levelTwoSelect = lotteryCategoryRes.getLotteryCategory().getLevelTwo();
        List<String> levelThreeSelect = lotteryCategoryRes.getLotteryCategory().getLevelThree();
        List<String> levelFourSelect = lotteryCategoryRes.getLotteryCategory().getLevelFour();
        log.info("查询分类耗时:t3:{}", System.currentTimeMillis());

        Future<List<LotteryCategoryVo>> levelFourFuture = lotteryCategoryTaskExecutor.submit(CallableWrapper.of(() -> selectChildrenAll(levelThreeSelect)));
        Future<List<LotteryCategoryVo>> levelThreeFuture = lotteryCategoryTaskExecutor.submit(CallableWrapper.of(() -> selectChildrenAll(levelTwoSelect)));
        Future<List<LotteryCategoryVo>> levelTwoFuture = lotteryCategoryTaskExecutor.submit(CallableWrapper.of(() -> selectChildrenAll(levelOneSelect)));
        Future<List<LotteryCategoryVo>> levelOneFuture = lotteryCategoryTaskExecutor.submit(CallableWrapper.of(() -> selectByLevel(1)));
        Future<Long> skuCountFuture = lotteryCategoryTaskExecutor.submit(CallableWrapper.of(() -> selectSkuCount(LotteryCategoryRequest
                .builder()
                .categoryIds(levelFourSelect)
                .page(0)
                .size(0)
                .build())));


        Long skuCount = null;
        List<LotteryCategoryVo> levelOne = null;
        List<LotteryCategoryVo> levelTwo = null;
        List<LotteryCategoryVo> levelThree = null;
        List<LotteryCategoryVo> levelFour = null;
        try {
            skuCount = skuCountFuture.get();
            levelOne = levelOneFuture.get();
            levelTwo = levelTwoFuture.get();
            levelThree = levelThreeFuture.get();
            levelFour = levelFourFuture.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        log.info("查询分类耗时:t2:{}", System.currentTimeMillis());
        return LotteryCategoryQueryVo.builder()
                .id(lotteryCategoryRes.getId())
                .isSelect(true)
                .levelOne(levelOne)
                .levelTwo(levelTwo)
                .levelThree(levelThree)
                .levelFour(levelFour)
                .levelOneSelect(levelOneSelect)
                .levelTwoSelect(levelTwoSelect)
                .levelThreeSelect(levelThreeSelect)
                .levelFourSelect(levelFourSelect)
                .count(skuCount)
                .build();

    }
    public LotteryCategoryQueryVo getCategory(String activityCode) {
        log.info("查询分类耗时:t1:{}", System.currentTimeMillis());

        LotteryCategoryRes lotteryCategoryRes = lotteryActivityService.queryCategory(activityCode);
        if (ObjectUtils.isEmpty(lotteryCategoryRes)) {
            return LotteryCategoryQueryVo.builder().isSelect(false).build();
        }

        List<String> levelOneSelect = lotteryCategoryRes.getLotteryCategory().getLevelOne();
        List<String> levelTwoSelect = lotteryCategoryRes.getLotteryCategory().getLevelTwo();
        List<String> levelThreeSelect = lotteryCategoryRes.getLotteryCategory().getLevelThree();
        List<String> levelFourSelect = lotteryCategoryRes.getLotteryCategory().getLevelFour();
        log.info("查询分类耗时:t3:{}", System.currentTimeMillis());

        Future<List<LotteryCategoryVo>> levelFourFuture = lotteryCategoryTaskExecutor.submit(CallableWrapper.of(() -> selectChildrenAll(levelThreeSelect)));
        Future<List<LotteryCategoryVo>> levelThreeFuture = lotteryCategoryTaskExecutor.submit(CallableWrapper.of(() -> selectChildrenAll(levelTwoSelect)));
        Future<List<LotteryCategoryVo>> levelTwoFuture = lotteryCategoryTaskExecutor.submit(CallableWrapper.of(() -> selectChildrenAll(levelOneSelect)));
        Future<List<LotteryCategoryVo>> levelOneFuture = lotteryCategoryTaskExecutor.submit(CallableWrapper.of(() -> selectByLevel(1)));
        Future<Long> skuCountFuture = lotteryCategoryTaskExecutor.submit(CallableWrapper.of(() -> selectSkuCount(LotteryCategoryRequest
                .builder()
                .categoryIds(levelFourSelect)
                .page(0)
                .size(0)
                .build())));


        Long skuCount = null;
        List<LotteryCategoryVo> levelOne = null;
        List<LotteryCategoryVo> levelTwo = null;
        List<LotteryCategoryVo> levelThree = null;
        List<LotteryCategoryVo> levelFour = null;
        try {
            skuCount = skuCountFuture.get();
            levelOne = levelOneFuture.get();
            levelTwo = levelTwoFuture.get();
            levelThree = levelThreeFuture.get();
            levelFour = levelFourFuture.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        log.info("查询分类耗时:t2:{}", System.currentTimeMillis());
        return LotteryCategoryQueryVo.builder()
                .id(lotteryCategoryRes.getId())
                .isSelect(true)
                .levelOne(levelOne)
                .levelTwo(levelTwo)
                .levelThree(levelThree)
                .levelFour(levelFour)
                .levelOneSelect(levelOneSelect)
                .levelTwoSelect(levelTwoSelect)
                .levelThreeSelect(levelThreeSelect)
                .levelFourSelect(levelFourSelect)
                .count(skuCount)
                .build();

    }
    @Bean("lotteryCategoryTaskExecutor")
    public ThreadPoolTaskExecutor lotteryCategoryTaskExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setCorePoolSize(10);
        threadPoolTaskExecutor.setMaxPoolSize(20);
        threadPoolTaskExecutor.setKeepAliveSeconds(200);
        threadPoolTaskExecutor.setQueueCapacity(100);
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        return threadPoolTaskExecutor;
    }

CountDownLatch写法多线程调用:

    public List<EnvelopeRainShopVO> checkShops(List<String> shopIds,String activityCode) {
        log.info("校验门店入参,活动代码为:{},门店为:{}",activityCode,shopIds);
        List<MissionMappingDO> byShopId = missionMappingDataMapperEx.findByShopId(shopIds, MissionBizTypeEnum.ENVELOPE_RAIN.getBizId());
        List<EnvelopeRainShopVO> res = Collections.synchronizedList(new ArrayList<>());
        String circuitBreakConfig = null;
        try {
            circuitBreakConfig = ConfigManager.getInstance().getConfig("ACTIVITY", "rain-check-shop-break-config");
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        // 降级开关
        if (Objects.equals("1", circuitBreakConfig)) {
            log.info("checkShops直接通过校验");
            return res;
        }
        if(CollectionUtils.isEmpty(byShopId)){
            return res;
        }

        //很多门店在同一个活动下
        AtomicBoolean flag = new AtomicBoolean(false);
        Map<String,ActivityInfo> activityInfoMap = new ConcurrentHashMap<>();
        CountDownLatch cdl = new CountDownLatch(byShopId.size());
        for (MissionMappingDO mission : byShopId) {
            redRainCheckShopTaskExecutor.submit(()->{
                try {
                    ActivityInfo activityInfo = activityInfoMap.get(mission.getRefId());
                    if (Objects.isNull(activityInfo)) {
                        activityInfo = activityCoreService.getActivityInfo(mission.getRefId());
                        if(Objects.isNull(activityInfo)){
                            return;
                        }
                        activityInfoMap.put(mission.getRefId(), activityInfo);
                    }

                    if (activityInfo.getActivityCode().equals(activityCode)) {
                        return;
                    }
                    Shop shopById = shopService.getAnyShopById(mission.getShopRef());
                    if(Objects.isNull(shopById)){
                        throw new GenericBusinessException(mission.getShopRef()+"门店不存在");
                    }
                    if (activityInfo.getStatus() == ActivityStatus.NOT_ENABLED
                            || activityInfo.getStatus() == ActivityStatus.NOT_START
                            || activityInfo.getStatus() == ActivityStatus.AVAILABLE
                            || activityInfo.getStatus() == ActivityStatus.AUDITING) {
                        res.add(EnvelopeRainShopVO.builder()
                                .shopId(mission.getShopRef())
                                .shopName(shopById.getShopName())
                                .activityCode(mission.getRefId())
                                .build());
                    }
                } catch (Exception e) {
                    flag.set(true);
                    log.error("RainMissionRuleServiceImpl.checkShops error",e);
                } finally {
                    cdl.countDown();
                }
            });
        }
        try {
            cdl.await();
        } catch (InterruptedException e) {
            log.error("RainMissionRuleServiceImpl.checkShops error",e);
        }
        if (flag.get()){
            throw new GenericBusinessException("门店校验错误");
        }
        Map<String,EnvelopeRainShopVO> map =new HashMap<>();
        res.stream().forEach(n->{
            if(!map.containsKey(n.getActivityCode())){
                map.put(n.getActivityCode(),n);
            }else {
                map.get(n.getActivityCode()).setShopName(map.get(n.getActivityCode()).getShopName()+","+n.getShopName());
                map.get(n.getActivityCode()).setShopId(map.get(n.getActivityCode()).getShopId()+","+n.getShopId());
            }
        });
        Set<String> keys = map.keySet();
        List<EnvelopeRainShopVO> res1 = new ArrayList<>();
        for(String key : keys){
            res1.add(map.get(key));
        }
        log.info("校验门店出参,已有活动的门店为:{}",res1);
        return res1;
    }

    @Bean
    public ThreadPoolTaskExecutor redRainCheckShopTaskExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setCorePoolSize(10);
        threadPoolTaskExecutor.setKeepAliveSeconds(200);
        threadPoolTaskExecutor.setMaxPoolSize(10);
        threadPoolTaskExecutor.setQueueCapacity(500);
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        return threadPoolTaskExecutor;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值