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