前几天写了一个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(); }
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(); } });
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();
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