自定义线程池使用-countDownLatch卡死问题解决

    public void weatherConditionList(String uniqueId) {
        //可用CPU数
        int availableProcessors = Runtime.getRuntime().availableProcessors();
        ThreadPoolExecutor threadPoolExecutor =
                new ThreadPoolExecutor(availableProcessors/2 + 1, availableProcessors/2 + 1, 0L, TimeUnit.MILLISECONDS,
                        new LinkedBlockingQueue<Runnable>(availableProcessors * 10000),
                        new ThreadFactoryBuilder().setNameFormat("weather-Condition-pool-Thread-%d").build(),
                        new ThreadPoolExecutor.AbortPolicy());
        bizLogger.info("天气实况查询开始:uniqueId="+uniqueId);
        try{
            //查询所有租户绑定的城市id
            List<String> cityIdList= adsOwnershipCityRelDao.selectCity(null);
            if (CollectionUtils.isEmpty(cityIdList)){
                return;
            }
            //countDownLatch总数为查出来的城市数量,用来保证线程全部执行完之后再执行insert操作
            CountDownLatch countDownLatch=new CountDownLatch(cityIdList.size());
            List<AdsWeather> list=Collections.synchronizedList(new ArrayList<AdsWeather>());
            for (String cityId:cityIdList) {
                threadPoolExecutor.execute(()->{
                    //根据cityId查询天气实况
                    AdsWeather ods= weatherCondition(cityId);
                    if (ods!=null){
                        list.add(ods);
                    }
                    //每次减一
                    countDownLatch.countDown();
                });
            }
            //当countDownLatch等于0才能往下走
            countDownLatch.await();
            if (!CollectionUtils.isEmpty(list)){
                //将天气实况存入数据库
                adsWeatherDao.batchInsert(list);
            }
        }catch (Exception e){
            bizLogger.error("天气实况批量查询报错",e);
        }finally {
            threadPoolExecutor.shutdown();
        }
        bizLogger.info("天气实况查询结束:uniqueId="+uniqueId);
    }

CountDownLatch卡死问题:
一、线程池拒绝策略如果用的不是AbortPolicy,如果阻塞队列满了新的任务会被抛弃而且不抛弃异常,那countDownLatch永远不会等于0, countDownLatch.await()会一直阻塞。
拒绝策略
AbortPolicy(默认):直接抛出RejectedExecutionException异常阻止系统正常运行
CallerRunsPolicy:调用者运行(让调用者线程执行任务,作为额外的线程执行任务,非线程池内部线程),不抛任务和异常,而是将任务回退给调用者,从而降低新任务的流量
DiscardOldPolicy:抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试再次提交
DiscardPolicy:直接丢弃任务,不处理也没有异常。如果允许任务丢失,这是最好的解决方式
二、线程执行时报错,而多线程抛出的异常无法被正常捕获,这样countDownLatch.countDown()也会一直阻塞

public void weatherConditionList(String uniqueId) {
        //可用CPU数
        int availableProcessors = Runtime.getRuntime().availableProcessors();
        ThreadPoolExecutor threadPoolExecutor =
                new ThreadPoolExecutor(availableProcessors/2 + 1, availableProcessors/2 + 1, 0L, TimeUnit.MILLISECONDS,
                        new LinkedBlockingQueue<Runnable>(availableProcessors * 10000),
                        new ThreadFactoryBuilder().setNameFormat("weather-Condition-pool-Thread-%d").build(),
                        new ThreadPoolExecutor.AbortPolicy());
        bizLogger.info("天气实况查询开始:uniqueId="+uniqueId);
        try{
            //查询所有租户绑定的城市id
            List<String> cityIdList= adsOwnershipCityRelDao.selectCity(null);
            if (CollectionUtils.isEmpty(cityIdList)){
                return;
            }
            //countDownLatch总数为查出来的城市数量,用来保证线程全部执行完之后再执行insert操作
            CountDownLatch countDownLatch=new CountDownLatch(cityIdList.size());
            List<AdsWeather> list=Collections.synchronizedList(new ArrayList<AdsWeather>());
            for (String cityId:cityIdList) {
                threadPoolExecutor.execute(()->{
                	//这里抛出的异常没有被正常捕获
                	int a=10/0;
                    //根据cityId查询天气实况
                    AdsWeather ods= weatherCondition(cityId);
                    if (ods!=null){
                        list.add(ods);
                    }
                    //每次减一
                    countDownLatch.countDown();
                });
            }
            //当countDownLatch等于0才能往下走
            countDownLatch.await();
            if (!CollectionUtils.isEmpty(list)){
                //将天气实况存入数据库
                adsWeatherDao.batchInsert(list);
            }
        }catch (Exception e){
            bizLogger.error("天气实况批量查询报错",e);
        }finally {
            threadPoolExecutor.shutdown();
        }
    }

解决办法在线程内部try catch,在finally里执行减一操作

    public void weatherConditionList(String uniqueId) {
        //可用CPU数
        int availableProcessors = Runtime.getRuntime().availableProcessors();
        ThreadPoolExecutor threadPoolExecutor =
                new ThreadPoolExecutor(availableProcessors + 1, availableProcessors + 1, 0L, TimeUnit.MILLISECONDS,
                        new LinkedBlockingQueue<Runnable>(1024),
                        new ThreadFactoryBuilder().setNameFormat("weather-Condition-pool-Thread-%d").build(),
                        new ThreadPoolExecutor.AbortPolicy());
        bizLogger.info("天气实况查询开始:uniqueId="+uniqueId);
        try{
            //查询所有租户绑定的城市id
            List<String> cityIdList= adsOwnershipCityRelDao.selectCity(null);
            if (CollectionUtils.isEmpty(cityIdList)){
                return;
            }
            //countDownLatch总数为查出来的城市数量,用来保证线程全部执行完之后再执行insert操作
            CountDownLatch countDownLatch=new CountDownLatch(cityIdList.size());
            List<AdsWeather> list=Collections.synchronizedList(new ArrayList<AdsWeather>());
            for (String cityId:cityIdList) {
                threadPoolExecutor.execute(()->{
                    try{
                        int i=10/0;
                        AdsWeather ods= weatherCondition(cityId);
                        if (ods!=null){
                            list.add(ods);
                        }
                    }catch (Exception e){
                        bizLogger.error("天气实况查询线程报错",e);
                    }finally {
                        //每次减一
                        countDownLatch.countDown();
                    }
                });
            }
            //当countDownLatch等于0才能往下走
            countDownLatch.await();
            if (!CollectionUtils.isEmpty(list)){
                //将天气实况存入数据库
                adsWeatherDao.batchInsert(list);
            }
        }catch (Exception e){
            bizLogger.error("天气实况批量查询报错",e);
        }finally {
            threadPoolExecutor.shutdown();
        }
    }

你可能感兴趣的:(java)