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:使用多線程時,需要給線程命名(方便線程跟蹤)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章