CountDownLatch实际应用

CountDownLatch 实际应用

  • 描述
  • 代码
  • 注意事项

描述

使用CountDownLatch控制多线程获取数据,并汇集成一个集合返回。

代码

  @ApiOperation(value = "Mis(时间推移)统计", notes = "Mis(时间推移)统计")
    @RequestMapping(path = "/mis/MisDateSumaryRpt", method = RequestMethod.GET)
    public RestResult<List<MisPrcInputResult>> MergeMisRpt(@RequestParam(name = "vCurDate", required = true) String vCurDate,
                                                           @RequestParam(name = "vMisType", required = true) String vMisType,
                                                           @RequestParam(name = "vSumaryType", required = true, defaultValue = "2") String vSumaryType,
                                                           @RequestParam(name = "vGroupBy", required = true) String vGroupBy,
                                                           @RequestParam(name = "vWhere", required = false) String vWhere,
                                                           @RequestParam(name = "vTop", required = true, defaultValue = "1") Integer vTop,
                                                           @RequestParam(name = "token", required = true) String token) throws ParseException {

        RestResult<List<MisPrcInputResult>> rs = new RestResult<>();
        rs.setData(new ArrayList<MisPrcInputResult>());
        rs.setResult(1);
        rs.setMsg("获取成功");

        Date vdate =  DateUtils.formatDate(vCurDate);

        //为性能考虑,限制过长的时间跨度
        if (vTop > 12 || vTop <0 ) {
            rs.setResult(0);
            rs.setMsg("时间跨度应在1 到 12之间");
            return rs;
        }
     final CountDownLatch latch = new CountDownLatch(vTop);

        //时间跨度超过1
        for (Integer i =0; i<vTop;i++ ) {

            //默认为月
            Date d = DateUtils.addMonth(vdate, -i * ("1".equals(vSumaryType)?12:1));

            //开启多线程获取数据,并汇集
            new Thread(() -> {
                try {
                    System.out.println("vCurDate:" + formatString(d,"yyyy-MM-dd"));
                    RestResult<List<MisPrcInputResult>> localRs = biz.getMisPrc(d, vMisType, vSumaryType, vGroupBy, vWhere, "");

                    if (1 == localRs.getResult() && !CollectionUtils.isEmpty(localRs.getData())) {
                        synchronized (rs)
                        {
                            List<MisPrcInputResult> ls = rs.getData();
                            for (MisPrcInputResult r : localRs.getData()) {
                                ls.add(r);
                            }
                            if(localRs.getResult()!=1)
                            {
                                rs.setResult(localRs.getResult());
                                rs.setMsg(localRs.getMsg());
                            }
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                finally {
                    latch.countDown();
                    System.out.println("剩下" + latch.getCount()+"个未完成");
                }
            },"Mis_Fetch_Data_Thread_"+i).start();
        }
        //等待线程收集齐数据
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        rs.getData().sort(( s1,s2)->{
            return   s1.getSumaryDate().compareTo(s2.getSumaryDate());
        });
        return rs;
    }

注意事项

1:多线程的数量需要控制,并不是越多越好。
2:每个程线必须 在结速时调用 latch.countDown(); 建议 放在finally里面。
3:写入集合时,需要加锁synchronized。
4:只有全部线程返回成功,才是最终的成功,如有其中任何一个失败,最终结果都是失败。
5:使用多线程时,需要给线程命名(方便线程跟踪)。

你可能感兴趣的:(随笔,Java,基础,多线程)