同步屏障CyclicBarrier

它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续运行。CyclicBarrier还提供一个更高级的构造函数CyclicBarrier(int parties,Runnable barrier-Action),用于在线程到达屏障时,优先执行barrierAction,方便处理更复杂的业务场景,比如说:CyclicBarrier可以用于多线程计算数据,最后合并计算结果的场景。例如,用一个Excel保存了用户所有银行流水,每个Sheet保存一个账户近一年的每笔银行流水,现在需要统计用户的日均银行流水,先用多线程处理每个sheet里的银行流水,都执行完之后,得到每个sheet的日均银行流水,最后,再用barrierAction用这些线程的计算结果,计算出整个Excel的日均银行流水。

/**
 *  CyclicBarrier操作Excel
 */
public class BankWaterService implements Runnable {
	List userList;
	FileInputStream inputStream;
	
	/**
	 * 创建3个屏障,处理完之后执行当前类的run方法
	 */
	private CyclicBarrier c = new CyclicBarrier(3, this);
	/**
	 * 假设只有3个sheet,所以只启动3个线程
	 */
	private static ExecutorService executor = Executors.newFixedThreadPool(3);
	/**
	 * 保存每个sheet计算出的银流结果
	 */
	private ConcurrentHashMap sheetBankWaterCount = new ConcurrentHashMap();
	
	
	public void testBefore() throws IOException {
		inputStream = new FileInputStream("D:\\测试.xlsx");
		userList = new ArrayList();
		userList.add(new User("Jack","张三",true,"[email protected]"));
		userList.add(new User("Rose","李华",false,"[email protected]"));
		userList.add(new User("Tom","王五",true,"[email protected]"));
	}
	
	
	private void count() throws Exception {
		testBefore();
		//1、读取工作簿
		XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
		for (User user : userList) {
			executor.execute(new Runnable() {
				@Override
				public void run() {
					//2、读取第一个工作表
					XSSFSheet sheet = workbook.getSheet(user.getName());
					//遍历行
					Double val = 0.00;
					for(int r = sheet.getFirstRowNum(); r <= sheet.getLastRowNum(); r++) { 
						//3、读取行;读取第3行
						XSSFRow row = sheet.getRow(r);
						//4、读取单元格;读取第3行第3列
						XSSFCell cell = row.getCell(0);
						System.out.println(user.getName()+"第"+r+"行第0列单元格的内容为:" + cell.getNumericCellValue());
						val += cell.getNumericCellValue();
					}
					// 计算当前sheet的银流数据,计算代码省略
					sheetBankWaterCount.put(user.getName(), val);
					// 银流计算完成,插入一个屏障
					try {
						c.await();
					} catch (InterruptedException | BrokenBarrierException e) {
						e.printStackTrace();
					}
				}
			});
		}
		workbook.close();
		inputStream.close();
	}

	@Override
	public void run() {
		double result = 0;
		// 汇总每个sheet计算出的结果
		for (Entry sheet : sheetBankWaterCount.entrySet()) {
			result += sheet.getValue();
		}
		// 将结果输出
		sheetBankWaterCount.put("result", result);
		System.out.println(result);
	}

	public static void main(String[] args) throws Exception {
		BankWaterService bankWaterCount = new BankWaterService();
		bankWaterCount.count();
		executor.shutdown();
	}
}
测试.xlsx里面每个用户名是sheet名称,项目实际中处理Excel利器。


你可能感兴趣的:(Java,JavaConcurrency)