Fork/Join 实战中的实例

来源:互联网 发布:zepto.js鼠标滑动事件 编辑:程序博客网 时间:2024/05/16 02:51

fork/join到底有多强大?废话不多说,直接看栗子吧

public List<VoucherInfoVo> calculationVoucherPay(String modelNo,SingletonScrollBar singletonScrollBar) throws Exception {CwVoucherModel cwVoucherModel = null;CwVoucherModelExample exampleModel = new CwVoucherModelExample();exampleModel.createCriteria().andModelNoEqualTo(modelNo).andIsDeleteEqualTo((short) 0);;List<CwVoucherModel> listModel = cwVoucherModelMapper.selectByExample(exampleModel);if (listModel != null && listModel.size() > 0) {cwVoucherModel = listModel.get(0);}singletonScrollBar.setNode(cwVoucherModel.getModelName());// 首先找出对应的模板组信息CwVoucherModelInfoExample example = new CwVoucherModelInfoExample();example.createCriteria().andModelNoEqualTo(modelNo).andIsDeleteEqualTo((short) 0);example.setOrderByClause("id asc");//获取所有的城市编码 Map<String,String> cityCode=ListChangeToMap(cwVoucherCityCodeInfoMapper.findAllCityCode());// 获取记账日期List<VoucherResultVo> dueDates = cwVoucherPayResultMapper.getAccountDate();String[] accountDate = null;if (dueDates.size() > 0) {accountDate = TimeUtil.calculateTime(dueDates.get(0).getDueDate());}else {return null;}List<CwVoucherModelInfo> list = cwVoucherModelInfoMapper.selectByExample(example);List<VoucherInfoVo> resutList = new ArrayList<VoucherInfoVo>();int count = 0;// 分录号if (list != null) {singletonScrollBar.setTemp(list.size());ForkJoinPool forkJoinPool = new ForkJoinPool();CountTaskPay task = new CountTaskPay(accountDate, 0,list.size() - 1, list, count, singletonScrollBar,cityCode);Future<List<VoucherInfoVo>> future = forkJoinPool.submit(task);resutList = future.get();}// 生成凭证所需bean类 返回return resutList;}

         这是统计一个凭证信息的,每一个凭证信息都需要去数据库就行sql查询,表的数据大小大概在20W左右,每一个凭证查询的条件至少在 3个以上,要命的是用到了sum,一个凭证模板里面可能包含10000个左右的sql查询合统计,如果在没有用到fork/join这么一个框架去跑的话,我也尝试用一般的for循环去统计,而线程池又不能很好地控制统计每一个sql结果(就是最后我要得到的那个resultList),单独用for去做这件事,我统计了一下,大概用时 10分钟左右,当时就石化了,这么结果怎么能接受,而我也仔细研究过所写的sql,sql语句没有什么问题,关键是查询,当然也不能给整个数据放到内存里面去,这样内存会爆炸的。于是就尝试用fork/join框架来跑整个结果了,结果很让我吃鲸,整个用时1分30秒左右,对于这样一个大数据统计加导出,这个用时还是能接受的。下面再看看fork/join具体是怎么工作的


@SuppressWarnings("serial")class CountTaskFack extends RecursiveTask<List<VoucherInfoVo>> {private static final int threshold = 2;// 阈值private String[] accountDate;private int start;private int end;private int count;private SingletonScrollBar singletonScrollBar;private List<CwVoucherModelInfo> listModel;private Map<String,String> cityCode;public CountTaskFack(String[] accountDate, int start, int end,List<CwVoucherModelInfo> list, int count,SingletonScrollBar singletonScrollBar,Map<String,String> cityCode) {this.accountDate = accountDate;this.start = start;this.end = end;this.listModel = list;this.count = count;this.singletonScrollBar = singletonScrollBar;this.cityCode=cityCode;}@Overrideprotected List<VoucherInfoVo> compute() {DecimalFormat df = new DecimalFormat("######0.00");List<VoucherInfoVo> list = new ArrayList<>();boolean compute = (end - start) <= threshold;if (compute) {for (int i = start; i <= end; i++) {CwVoucherModelInfo real = listModel.get(i);singletonScrollBar.setCurrentTask(singletonScrollBar.getCurrentTask() + 1);singletonScrollBar.setCount(i + 1);VoucherInfoVo vo = new VoucherInfoVo();vo.setBusinessAccounting1(VoucherServerUtil.getRealName(real.getAccountingAux1()));vo.setCode1(VoucherServerUtil.getCode(real.getAccountingAux1(), real, cityCode,""));vo.setName1(VoucherServerUtil.getName(real.getAccountingAux1(), real,""));vo.setBusinessAccounting2(VoucherServerUtil.getRealName(real.getAccountingAux2()));vo.setCode2(VoucherServerUtil.getCode(real.getAccountingAux2(), real, cityCode,""));vo.setName2(VoucherServerUtil.getName(real.getAccountingAux2(), real,""));vo.setBusinessAccounting3(VoucherServerUtil.getRealName(real.getAccountingAux3()));vo.setCode3(VoucherServerUtil.getCode(real.getAccountingAux3(), real, cityCode,""));vo.setName3(VoucherServerUtil.getName(real.getAccountingAux3(), real,""));vo.setAccountDate(accountDate[0]);vo.setAccountingGap(accountDate[2]);vo.setVoucherNo(accountDate[3]);vo.setBusinessDate(accountDate[0]);vo.setAuxiliaryAccountingDate(accountDate[0]);vo.setExpireDate(accountDate[0]);vo.setEntryNo(i + 1 + "");vo.setAbstractInfo(real.getAccountingAbs());vo.setAuxiliaryAbstractInfo(real.getAccountingAbs());vo.setCompany(real.getAccountNum());vo.setSubjectInfo(real.getSubjectNum());// 然后根据信息进行分组统计FactAccountVo conditions = getFactSqlConditionResult(real);if (conditions.getCitys().size() > 0) {int cityCount = 0;for (String city : conditions.getCitys()) {cityCount++;if (cityCount==conditions.getCitys().size()) {//统计每一次城市循环 增加滚动条准确度if (Double.valueOf(df.format(((double) (i + 1) / (double) singletonScrollBar.getTemp()) * 100)) >= singletonScrollBar.getPercentage()) {singletonScrollBar.setPercentage(Double.valueOf(df.format(((double) (i + 1) / (double) singletonScrollBar.getTemp()) * 100)));}}VoucherInfoVo voc = new VoucherInfoVo();voc.setBusinessAccounting1(VoucherServerUtil.getRealName(real.getAccountingAux1()));voc.setCode1(VoucherServerUtil.getCode(real.getAccountingAux1(), real, cityCode,city));voc.setName1(VoucherServerUtil.getName(real.getAccountingAux1(), real,city));voc.setBusinessAccounting2(VoucherServerUtil.getRealName(real.getAccountingAux2()));voc.setCode2(VoucherServerUtil.getCode(real.getAccountingAux2(), real, cityCode,city));voc.setName2(VoucherServerUtil.getName(real.getAccountingAux2(), real,city));voc.setBusinessAccounting3(VoucherServerUtil.getRealName(real.getAccountingAux3()));voc.setCode3(VoucherServerUtil.getCode(real.getAccountingAux3(), real, cityCode,city));voc.setName3(VoucherServerUtil.getName(real.getAccountingAux3(), real,city));voc.setAccountDate(accountDate[0]);voc.setBusinessDate(accountDate[0]);voc.setVoucherNo(accountDate[3]);voc.setAccountingGap(accountDate[2]);voc.setAuxiliaryAccountingDate(accountDate[0]);voc.setExpireDate(accountDate[0]);voc.setEntryNo(i + 1 + "");voc.setAbstractInfo(real.getAccountingAbs());voc.setAuxiliaryAbstractInfo(real.getAccountingAbs());voc.setCompany(real.getAccountNum());voc.setSubjectInfo(real.getSubjectNum());SelectConditionVo record = new SelectConditionVo();record.setCity(city);record.setDate(accountDate[4]);record.setSum(getFactSqlSumResult(real));record.setFactAccountVo(conditions);singletonScrollBar.setCurrentNode(JSON.toJSONString(record));VoucherResultVo result = cwVoucherFactResultMapper.getFactSheet(record);logger.info("count=" + i + 1 + "城市结果:"+ JSON.toJSONString(result));if (result == null|| result.getTotalfee() == null|| result.getTotalfee().equals(new BigDecimal(0))) {cityCount++;if (cityCount == conditions.getCitys().size()) {// 如果所有城市都没有统计出来值// 那么分录号减一singletonScrollBar.getTaskCount().add(i + 1);count--;}continue;}voc.setTotalFee(result == null ? "" : result.getTotalfee() == null ? "" : result.getTotalfee() + "");if (!StringUtil.checkIsNull(real.getAccountDir())) {if (real.getAccountDir().equals("借方")) {voc.setDebtorMoney(result == null ? "": result.getTotalfee() == null ? "": result.getTotalfee() + "");voc.setDirection("1");} else {voc.setDirection("0");voc.setLenderMoney(result == null ? "": result.getTotalfee() == null ? "": result.getTotalfee() + "");}}list.add(voc);}} else {if (Double.valueOf(df.format(((double) (i + 1) / (double) singletonScrollBar.getTemp()) * 100)) >= singletonScrollBar.getPercentage()) {singletonScrollBar.setPercentage(Double.valueOf(df.format(((double) (i + 1) / (double) singletonScrollBar.getTemp()) * 100)));}SelectConditionVo record = new SelectConditionVo();record.setSum(getFactSqlSumResult(real));record.setFactAccountVo(conditions);record.setDate(accountDate[4]);singletonScrollBar.setCurrentNode(JSON.toJSONString(record));VoucherResultVo result = cwVoucherFactResultMapper.getFactSheet(record);if (result == null|| result.getTotalfee() == null|| result.getTotalfee().equals(new BigDecimal(0))) {count--;singletonScrollBar.getTaskCount().add(i + 1);continue;}vo.setTotalFee(result == null ? "" : result.getTotalfee() == null ? "" : result.getTotalfee() + "");if (!StringUtil.checkIsNull(real.getAccountDir())) {if (real.getAccountDir().equals("借方")) {vo.setDebtorMoney(result == null ? "" : result.getTotalfee() == null ? "" : result.getTotalfee() + "");vo.setDirection("1");} else {vo.setDirection("0");vo.setLenderMoney(result == null ? "" : result.getTotalfee() == null ? "" : result.getTotalfee() + "");}}list.add(vo);}}} else {// 任务大于阈值,那么就分裂成两个子任务计算int middle = (start + end) / 2;CountTaskFack leftTask = new CountTaskFack(accountDate, start,middle, listModel, count, singletonScrollBar,cityCode);CountTaskFack rightTask = new CountTaskFack(accountDate,middle + 1, end, listModel, count, singletonScrollBar,cityCode);// 执行子任务leftTask.fork();rightTask.fork();// 等待子任务执行完毕,并得到其结果List<VoucherInfoVo> left = leftTask.join();List<VoucherInfoVo> right = rightTask.join();list.addAll(left);list.addAll(right);}return list;}}




























































原创粉丝点击