Java Gold合格への道 ~並行処理・CyclicBarrier~
スポンサーリンク
こんにちは。たろすです。
今回は並行処理におけるCyclicBarrierについて説明します。
CyclicBarrierとは
CyclicBarrierは並行処理において各スレッドの足並みをそろえるときに使うクラスです。
例えば以下のようなコードを実行すると、
public class Main { public static void main(String[] args) { Thread t0 = new Thread(new Runnable() { public void run() { String threadName = Thread.currentThread().getName(); System.out.println(threadName + ":start"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(threadName + ":end"); } }); Thread t1 = new Thread(new Runnable() { public void run() { String threadName = Thread.currentThread().getName(); System.out.println(threadName + ":start"); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(threadName + ":end"); } }); Thread t2 = new Thread(new Runnable() { public void run() { String threadName = Thread.currentThread().getName(); System.out.println(threadName + ":start"); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(threadName + ":end"); } }); t0.start(); t1.start(); t2.start(); } }
Thread-0:start Thread-1:start Thread-2:start Thread-0:end Thread-1:end Thread-2:end
「Thread-0:end」と表示された後約4秒後に「Thread-1:end」と表示され、さらに約5秒後に「Thread-2:end」と表示されます。
一方で、CyclicBarrierを使うと、
public class Main { public static void main(String[] args) { CyclicBarrier barrier = new CyclicBarrier(2); Thread t0 = new Thread(new Runnable() { public void run() { String threadName = Thread.currentThread().getName(); System.out.println(threadName + ":start"); try { Thread.sleep(1000); barrier.await(); } catch (InterruptedException | BrokenBarrierException e) { e.printStackTrace(); } System.out.println(threadName + ":end"); } }); Thread t1 = new Thread(new Runnable() { public void run() { String threadName = Thread.currentThread().getName(); System.out.println(threadName + ":start"); try { Thread.sleep(5000); barrier.await(); } catch (InterruptedException | BrokenBarrierException e) { e.printStackTrace(); } System.out.println(threadName + ":end"); } }); Thread t2 = new Thread(new Runnable() { public void run() { String threadName = Thread.currentThread().getName(); System.out.println(threadName + ":start"); try { Thread.sleep(10000); barrier.await(); } catch (InterruptedException | BrokenBarrierException e) { e.printStackTrace(); } System.out.println(threadName + ":end"); } }); t0.start(); t1.start(); t2.start(); } }
Thread-1:start Thread-0:start Thread-2:start Thread-1:end Thread-0:end
実行から約10秒経ってから「Thread-0:end」と「Thread-1:end」が同時に表示されます。
ちなみに「Thread-2:end」が表示されないのはコンストラクタの引数(足並みをそろえるスレッドの数)を2に設定しているからです。
先に到着した二つのスレッドは先に行ってしまい、残りのスレッドは一つになってしまったので最後のスレッドは永遠に待機状態のままです。