Fork/Join 实战中的实例

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;
		}

		@Override
		protected 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;
		}
	}




























































  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值