JavaでのCountDownLatchによるマルチスレッド同期

4126 ワード

CountDownLatchの紹介
前のJava学習ノートでは、Javaでマルチスレッド同期を行う方法をいくつかまとめました.
1、synchronizedキーワードを同期する.
2.ロックインタフェースとその実装クラスReentrantLock、ReadWriteLockは同期を実現する.
3、信号量Semaphoreは同期を実現する.
ここでsynchronizedキーワードとロックは、同じリソースへの複数のスレッドの同時アクセスの問題を解決します.信号量Semaphoreは、マルチコピーリソースの共有アクセスの問題を解決します.
今日は、Javaのもう一つのマルチスレッド同期支援クラス:CountDownLatchについて学びましょう.CountDownLatchの公式ドキュメントでは、他のスレッドで実行されている操作のセットが完了するまで、1つ以上のスレッドを待機させることができます.つまり、CountDownLatchは、あるスレッドまたは複数のスレッドを制御し、複数のスレッドがタスクを完了してから起動するのを待つようにします.CountDownLatchは主に複数のタスクの実行を同期するために使用され、他のsynchronizedキーワード、ロック、信号量とは異なり、共有リソースを同期するために使用されます.
CountDownLatchの実現原理の概要:
CountDownLatch内部にはカウンタが維持され、カウンタの値は完了するタスク数Nであり、このN個のタスクが完了するまで待つスレッドがCountDownLatchのawait()メソッドを呼び出して自分をスリープ待機状態にする必要がある.
タスクスレッドがタスクを完了するとCountDownLatchのcountDown()メソッドを呼び出して自分のタスクが完了したことを示すと、CountDownLatchのカウンタ値は1減少し、すべてのタスク完了式でカウンタの値は0になります.カウンタ値が0の場合、CountDownLatchはawait()メソッドによってスリープに入ったすべてのスレッドを起動します.
CountDownLatchの使用:
CountDownLatchの使用は主に3点あります.
1、CountDownLatchの宣言と初期化は、初期化時に完了待ちのタスク数を指定する必要があります.
2、あるタスクの完了時にCountDownLatchのcountDown()メソッドを呼び出し、CountDownLatchに自分のタスクが完了したことを報告する.
3、タスク完了待ちのスレッドCountDownLatchのawait()メソッドを呼び出すと、そのスレッドはスリープ状態になり、すべてのタスク数が完了した後にCountDownLatchのカウンタ値が0の場合、await()メソッドによるスリープ状態のスレッドが起動します.
Java 7同時プログラミング実戦マニュアルこの本のCountDownLatchの使用例に基づいて、CountDownLatchの使用詳細をいくつか改善しました.
10人の参加者と1人の司会者が参加する会議をシミュレートし、各参加者と司会者は他の参加者が出席して署名してから、会議を開始して発言する必要があります.このためには、まず、参加者が署名のために呼び出すarrive()メソッドを提供する管理クラスVideoConferenceを作成します.会議管理の所有者は、各参加者の署名を待つ司会者です.
public class VideoConference implements  Runnable{
    private final CountDownLatch countDownLatch;
    private int number;
    public VideoConference(int number) {
        this.number = number;
        this.countDownLatch = new CountDownLatch(number);//  Number          ,       ,       
    }
    public void arrive(String name){
        //         ,      ,       
        countDownLatch.countDown();//countDownLatch       1
        System.out.print("arrive:"+name+"
"); try{ countDownLatch.await();//await , countDownLatch 0 , // , System.out.print("name:"+name + " say:let's start..." +"
"); }catch (InterruptedException e){ e.printStackTrace(); } } public void run(){ System.out.print("has arrive:"+(number-countDownLatch.getCount())+"
"); try{ countDownLatch.await();//await , countDownLatch 0 , // , System.out.print("all arrived:"+(number-countDownLatch.getCount())+"
"); }catch (InterruptedException e){ e.printStackTrace(); } } }

参加者クラスParticipantを作成するには、次の手順に従います.
public class Participant implements  Runnable{
    private VideoConference videoConference;
    private String name;

    public Participant(String name, VideoConference videoConference) {
        this.name = name;
        this.videoConference = videoConference;
    }
    public void run(){
        try {
            //do something
            Thread.sleep(50);
            //
            videoConference.arrive(name);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }

    public static void main(String[] args){
        VideoConference videoConference = new VideoConference(10);
        Thread videoThread = new Thread(videoConference);
        videoThread.start();
        for(int i=0; i<10; i++){
            Thread thread = new Thread(new Participant("participant:"+i,videoConference));
            thread.start();
        }
    }
}

Participantクラスのmain関数は、まず10人の参加者が参加する会議を作成し、その後、10人の参加者を作成して1人ずつ署名し、10人の参加者が署名した後、各参加者と司会者が「呼び覚まされた」と発言します.
まとめ:
CountDownLatchクラスはマルチスレッド間の同期待ち、タスク協調の問題を解決し、あるプログラムの主機能を起動する前に、構成環境チェック、ネットワークチェックなどの複数のサブタスクを事前に完了する必要があるなどの類似のシーンに適用する.Javaでは,CountDownLatchを用いてマルチスレッド間の同期待ちを実現するほか,フェンス技術CyclicBarrierを用いてマルチスレッド間の同期待ち,タスク協調を実現することもできる.