Java-多线程之线程池是否需要关闭

Jmeter压力测试

背景

之前的文章Java—多线程之学了就要用-CountDownLatch中,用线程池处理相关业务的功能代码,在程序处理完毕后,线程池并未关闭,后来review代码的时候发现了这个问题,将线程池关闭。

上线之前通过jmeter进行压力测试。对比线程池关闭和不关闭时压力测试的情况。下面通过测试数据进行对比。

测试

  • 核心代码
@RestController
@RequestMapping("tbgl/tbjd")
public class TbjdController {
/**
     * 查询当前用户所有报表的填报进度情况
     * @param params
     * @return
     */
    @RequestMapping("/getRepProgress")
    public Map getRepProgress(@RequestParam Map params) {
        Map map = tbjdService.getRepProgress();
        map.put("code", 0);
        return map;
    }
}



@Service("tbjdService")
public class TbjdServiceImpl implements TbjdService {
    public Map getRepProgress(){
        final int PROCESSORS = Runtime.getRuntime().availableProcessors();
        Map tjMap = new HashMap(16);
        List> progressList  = Collections.synchronizedList(new ArrayList>());
       
        List> distList = reportDao.getDistRecordList();

        AtomicInteger finishedNum = new AtomicInteger(0);
        AtomicInteger unfinishedNum =  new AtomicInteger(0);
        AtomicInteger notStartedNum =  new AtomicInteger(0);
        CountDownLatch latch = new CountDownLatch(distList.size());

        int corePoolSize = distList.size() < PROCESSORS ? distList.size():PROCESSORS;

        ExecutorService pool = new ThreadPoolExecutor(corePoolSize*2, PROCESSORS*8,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue(1024), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());

        for (Map map:distList) {
            pool.execute(() -> {
                // ....业务代码

                // 填报单位总数
                long sum = 0;
                // 已上报单位数
                long ysbSl = 0;
      
                String status = "";
                if(ysbSl == 0){
                    // 未开始
                    status = "01";
                    notStartedNum.incrementAndGet();
                }else if(ysbSl == sum){
                    // 已完成
                    status = "03";
                    finishedNum.incrementAndGet();
                }else{
                    // 进行中
                    status = "02";
                    unfinishedNum.incrementAndGet();
                }
                Map progressMap = new HashMap(16);                
                progressMap.put("status",status);
                progressMap.put("sbqk",ysbSl+"/"+sum);
                progressMap.put("progress",Math.round((float) ysbSl/(float)sum*100));

                progressList.add(progressMap);
                latch.countDown();
            });
        }
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 关闭线程池
        pool.shutdown();
        System.out.println("计算任务处理完毕");

        tjMap.put("reportNum",distList.size());
        tjMap.put("unfinishedNum",unfinishedNum);
        tjMap.put("finishedNum",finishedNum);
        tjMap.put("notStartedNum",notStartedNum);
        tjMap.put("progressList",progressList);
        return tjMap;
    }
}
  • 测试任务

100个线程,运行5分钟

Java-多线程之线程池是否需要关闭_第1张图片

Java-多线程之线程池是否需要关闭_第2张图片

  • 运行结果

服务器配置

Java-多线程之线程池是否需要关闭_第3张图片

(1)未关闭线程池

87.7%的异常率,平均响应时间14757ms

创建线程数29478,峰值29372,线程全部处于驻留状态,运行了一段时间后,tomcat直接异常退出了

 

Java-多线程之线程池是否需要关闭_第4张图片

Java-多线程之线程池是否需要关闭_第5张图片

(2)关闭线程池(pool.shutdown())

异常率0.02%,平均响应时间2308ms

Java-多线程之线程池是否需要关闭_第6张图片

创建线程数216899,峰值1041,活动60

Java-多线程之线程池是否需要关闭_第7张图片

由压测结果可见,线程池在使用完毕后需要及时关闭,否则不能及时释放,导致在大量并发情况下,系统资源耗尽,程序异常退出

你可能感兴趣的:(#,Java-多线程,java,多线程,jmeter,压力测试)