线程同步之CyclicBarrier使用示例

前几天写了一个CountDownLatch使用示例,今天把CyclicBarrier的示例补上。

话说这日部门组织大家去吃大排档,有18个人。大排档的桌小,一桌只能4个人。大家工作完成时间不定,有人来的早有人来的晚,但约好所有人到齐才开吃。呃,这里假设所有人都一定会来(现实中可能有些人因为这样那样的原因去不了)。

因为18个人来齐才能开饭,我这里用CountDownLatch来对18人到的事件计数。

final CountDownLatch countDown = new CountDownLatch(18); // 18个人

并在主线程里

		try {
			countDown.await(); <span style="font-family: Arial, Helvetica, sans-serif;">// 等所有人到齐</span>
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

我们用一个CyclicBarrier对象表示能容下4个人的小桌人满、通知大排档老板

		final CountDownLatch firstSignal = new CountDownLatch(1); // 第一桌
		// 每4人一桌
		final CyclicBarrier barrier = new CyclicBarrier(4, new Runnable() {
			@Override
			public void run() {
				if (firstSignal.getCount() > 0) {
					System.out.println("老板,先开一桌!");
				} else {
					System.out.println("老板,再开一桌!");
				}
				firstSignal.countDown();
			}
		});

每个人来的时候报个到,18个人最后2人只能他们两人一桌,barrier对象指定的规则不适用,需要reset(),这将产生一个BrokenBarrierException。

		ExecutorService pool = Executors.newCachedThreadPool();
		for (int i = 0; i < 18; i++) {
			final int idx = i + 1;
			pool.execute(new Runnable() {
				@Override
				public void run() {
					try {
						Thread.sleep(random.nextInt(3000));
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println("第" + idx + "人到了");
					countDown.countDown();
					try {
						barrier.await(); // 等这桌人满或所有人到齐。
					} catch (InterruptedException e) {
						e.printStackTrace();
					} catch (BrokenBarrierException e) { // 最后2人会产生此异常。
						// e.printStackTrace();
						System.out.println("你来的可真晚," + idx); // 来的晚要被抱怨
					}
				}
			});
		}
		pool.shutdown();

在所有人到齐之后,显然有2人被barrier阻塞了,不能上桌需要如下处理

		try {
			countDown.await(); // 等所有人到齐
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		if (barrier.getNumberWaiting() != 0) {
			System.out.println("老板,给最后" + barrier.getNumberWaiting() + "个人单开一桌!");
			barrier.reset();
		}
		System.out.println("老板,我们人都到齐了,上菜吧");
程序输出如下:

第14人到了
第13人到了
第9人到了
第12人到了
老板,先开一桌!
第1人到了
第2人到了
第5人到了
第18人到了
老板,再开一桌!
第16人到了
第15人到了
第10人到了
第17人到了
老板,再开一桌!
第4人到了
第8人到了
第7人到了
第6人到了
老板,再开一桌!
第11人到了
第3人到了
老板,给最后2个人单开一桌!
老板,我们人都到齐了,上菜吧
你来的可真晚,11
你来的可真晚,3

代码下载请到我的github上:https://github.com/DowenLiu126/syncDemo

你可能感兴趣的:(java,多线程,同步)