EeBlog(テクニカルブログ)

第51回 シンクロナイザ編 CyclicBarrier

今回のテーマは「CyclicBarrier」です。

CyclicBarrierはスレッドセットのそれぞれが共通のバリアポイントに達するまで待機することを可能にする同期化支援機能です。 指定された数のスレッドがawaitメソッドを実行するまで待機させることができます。 CountDownLatchは繰り返し使用することができませんが、CyclicBarrierは待機中のスレッドが解放されたあとで再利用できます。

次のサンプルコードは前回のCountDownLatchをCyclicBarrierに変更したプログラムです。(J2SE5.0以上対応)

import java.io.BufferedOutputStream; 
import java.io.File; 
import java.io.FileOutputStream; 
import java.util.concurrent.Callable; 
import java.util.concurrent.CyclicBarrier; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors;

public class Main {

    private static final String TEXT = "abcdefghijklmnopqrstuvwxyz"; 
         public static void main(String[] args) throws Exception { 
        byte[] bytes = TEXT.getBytes(); 
        File[] files = { new File("output1.txt"), new File("output2.txt") }; 
        CyclicBarrier cyclicBarrier = new CyclicBarrier(files.length + 1); 
        ExecutorService executorService = Executors.newCachedThreadPool(); 
        for (File file : files) { 
            executorService.submit(new ICallable(cyclicBarrier, file, bytes)); 
        } 
        executorService.shutdown(); 
        cyclicBarrier.await(); 
        System.out.println("END"); 
    } 
}

class ICallable implements Callable<Object> {

    private CyclicBarrier cyclicBarrier; 
    private File file; 
    private byte[] bytes;

    public ICallable(CyclicBarrier cyclicBarrier, File file, byte[] bytes) { 
        this.cyclicBarrier = cyclicBarrier;  
        this.file = file; 
        this.bytes = bytes; 
    }

    public Object call() throws Exception { 
        BufferedOutputStream bufferedOutputStream = null; 
        try { 
            bufferedOutputStream
                = new BufferedOutputStream(new FileOutputStream(file)); 
            bufferedOutputStream.write(bytes); 
        } catch (Exception e) { 
            e.printStackTrace(); 
        } finally { 
            if (bufferedOutputStream != null) { 
                bufferedOutputStream.close(); 
            } 
            cyclicBarrier.await(); 
        } 
        return null; 
    }
}