線程同步之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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章