描述
使用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:使用多线程时,需要给线程命名(方便线程跟踪)。