[] --- CyclicBarrierを並行プログラミングの原則はじめに使用+

送信元アドレス:https://github.com/nieandsun/concurrent-study.git


原則1はじめに

CyclicBarrierを、中国語の翻訳は、循环屏障我々は、少なくとも二つのことを知ることができ、その名前の意味は:

  • これは、リサイクルが可能
  • それは障壁であります

1.1 CyclicBarrierを原則障壁

1.1.1のawaitはnull参照

次のような原理であります

  • (1)例えば、我々は(CyclicBarrierをは3つのスレッドを傍受しますデフォルトコンストラクタCyclicBarrierを(int型のパーティ)を使用して、)、三つのスレッドが同じ時間オープンでブロックされていてもよい以下のように、それは同時に、オンにしないことがあります。

ここに画像を挿入説明

  • (2)スレッド1および3は、各セットのスレッドのawait点(またはバリアポイント)に達したが、以下のようにスレッド2に、それらは、スレッド2を待機するしない場合は、次

ここに画像を挿入説明

  • (3/1)スレッド2はまた、到達点を待って、再度3つのスレッドをつかむ同時に実行するまで

ここに画像を挿入説明

  • (3/2)CyclicBarrierを事実は、より多くの牛があること、それだけで(あなたもbarrierActionを追加することができ、数がスレッドを傍受選択することはできませんコンストラクタCyclicBarrierを(int型のパーティー、RunnableをbarrierAction)を呼び出し)。これの実行タイミングがされた後barrierActionは1,2,3を待つスレッドは我々がここで興味深いの多くを行うことができ、ポイントに達しています。barrierAction場合は、上記の図は、次のように変更することができます:

ここに画像を挿入説明


時間はパラメータに1.1.2のawaitを通過したとき

ここで描画すると、最初に他のスレッドがのawait点に達していない場合は2秒後に、それ自身、実際には、CyclicBarrierをのawait方法はまた、例えば、2秒のスレッド2のawaitの着信待機時間を時間を渡すことができ、ではありません実行し、例外がスローされます。


それはどういう意味1.2 CyclicBarrierをサイクル

1.1は本当にただ原則CyclicBarrierをバリアの話されていますが、なぜそれは、循環障壁それと呼ばれていますか?
実際には、これは、彼らが依存実際にスレッド数を制御するかどうかCyclicBarrierを基礎となるソースたCountDownLatchのノウハウを見た人state变量

  • 「しかし、この状態でたCountDownLatchで初期化したら、 - 例えば、私がされたCountDownLatchに数5の初期状態を指定した状態が0に減少するまで、その後、カウントダウン後、私の状態はのawait自動的に解放し、1減少しましたあなただけの再利用は再利用することができない、減らすことができます。
  • しかし、私はまた、数5の初期状態を指定CyclicBarrierをしていた場合には、例えば、私は10個のスレッドを持っている、それは最初の最初の5つのスレッドのためにブロックされます-彼らはポイントのawaitに達した場合> - >ファイル名を指定して実行をつかむ、あなたは必要性がありません手動リセット状態数は、5つのスレッド後CyclicBarrierを自動的に同じ操作を実行します这就是所谓的循环的意思

2たCountDownLatch比較的単純でCyclicBarrierを

私の最後の記事を読んで、「- [並行プログラミング]たCountDownLatch原理はじめに+を使用するには、確かにCyclicBarrierをを感じるとのたCountDownLatch達成する、こちらをご覧の2.3概要」发令枪ああのような使い方を。

実際には、本当に好きですが、いくつかの違いがあります。

  • まず、たCountDownLatchは、実際には、他のスレッドをブロックするので、他のスレッドがある時点で同期を達成するというスレッドを作った;そしてCyclicBarrierをです
    ので、すべてのワーカースレッドがダウンして一緒に、指定したバリア、みんなに達するまで自身が、のawait呼び出して、自分の個々の労働者によってブロックされました行きます。
  • 第二に、たCountDownLatchカウンタ(状態)は、一度だけ使用することができ、CyclicBarrierをカウンタを繰り返し使用することができます。
  • そこでは、barrierActionのCyclicBarrierを、実際に私たちのために多くの操作空間を提供します
  • 用語の最後に、使用
    • 3つのスレッドがバリアポイントに到達するために後数指定された状態にI CyclicBarrierを同等である3、であり、3つのスレッド一緒にこの障壁を介して実行をつかむために点まで続きます。
    • そして、私たCountDownLatch 3つの指定状態の数が、私はあなたがいくつかのスレッドです気にしない、あなただけの私を与えるあなたは、私が設定していたバリアポイントを越えることができ、3回のカウントダウン。

3特定の使用


3.1 DEMO1 - 一緒に、次いでスレッドの指定された数の後awit時間経過していない、バリアポイントに到達すると、実行(サイクル傍受)をつかむために

  • コード
package com.nrsc.ch2.juctools;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;

@Slf4j
public class CyclicBarrierDemo1 {

    private final static int threadCount = 6;
    static CyclicBarrier barrier = new CyclicBarrier(2);

    public static void main(String[] args) throws InterruptedException {

        ExecutorService exec = Executors.newCachedThreadPool();
        for (int i = 0; i < threadCount; i++) {
            final int threadNum = i;

            //这里故意让后续线程晚一秒开启
            Thread.sleep(1000);
            exec.execute(() -> test(threadNum));
        }
        exec.shutdown();

    }

    private static void test(int threadNum) {
        try {
            log.info("线程{}已经准备就绪!", threadNum);
            barrier.await();
        } catch (InterruptedException e) {
            log.error("InterruptedException", e);
        } catch (BrokenBarrierException e) {
            log.error("BrokenBarrierException", e);
        }
        log.info("线程{}继续运行!", threadNum);
    }
}
  • テスト結果:

ここに画像を挿入説明


3.2 DEMO2 - より多くの時間よりも、バリアを越えて投げtは引き続き実行された後のawaitの着信時刻t、スレッドの前では、この時点での障壁と待ち時間に達します

package com.nrsc.ch2.juctools;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;

@Slf4j
public class CyclicBarrierDemo2 {
    private final static int threadCount = 2;
    static CyclicBarrier barrier = new CyclicBarrier(2);

    public static void main(String[] args) throws InterruptedException {

        ExecutorService exec = Executors.newCachedThreadPool();
        for (int i = 0; i < threadCount; i++) {
            final int threadNum = i;
            //这里故意让后续线程晚一秒开启
            Thread.sleep(2000);
            exec.execute(() -> test(threadNum));
        }
        exec.shutdown();

    }

    private static void test(int threadNum) {
        try {
            log.info("线程{}已经准备就绪!", threadNum);
            barrier.await(1, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            log.error("InterruptedException", e);
        } catch (BrokenBarrierException e) {
            log.error("BrokenBarrierException", e);
        } catch (TimeoutException e) {
            log.error("TimeoutException", e);
        }

        log.info("线程{}继续运行!", threadNum);
    }
}
  • テスト結果

ここに画像を挿入説明


使用barrierAction後の前に実行されている各スレッドの一部の情報は、統計的な障壁に達する - 3.3 demo3を

  • コード
package com.nrsc.ch2.juctools;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;

import java.util.Map;
import java.util.Random;
import java.util.concurrent.*;

@Slf4j
public class CyclicBarrierDemo3 {
    private final static int threadCount = 5;
    
    private static Map<String, Integer> concurrentHashMap = new ConcurrentHashMap();

    static CyclicBarrier barrier = new CyclicBarrier(5, () -> {
        MapUtils.verbosePrint(System.out, "前几个线程准备的数据", concurrentHashMap);
    });

    public static void main(String[] args) throws InterruptedException {

        ExecutorService exec = Executors.newCachedThreadPool();
        for (int i = 0; i < threadCount; i++) {
            final int threadNum = i;

            //这里故意让后续线程晚一秒开启
            Thread.sleep(1000);
            exec.execute(() -> test(threadNum));
        }
        exec.shutdown();

    }

    private static void test(int threadNum) {
        try {

            //模拟进行部分准备工作,并将准备的结果放入到Map容器
            int random = new Random().nextInt(10);
            log.info("线程{}准备的数据-{}",Thread.currentThread().getName(),random);
            concurrentHashMap.put(Thread.currentThread().getName(), random);

            log.info("线程{}已经准备就绪!", threadNum);
            barrier.await();

        } catch (InterruptedException e) {
            log.error("InterruptedException", e);
        } catch (BrokenBarrierException e) {
            log.error("BrokenBarrierException", e);
        }

        log.info("线程{}继续运行!", threadNum);
    }
}
  • テスト結果

ここに画像を挿入説明

公開された218元の記事 ウォンの賞賛295 ビュー500 000 +

おすすめ

転載: blog.csdn.net/nrsc272420199/article/details/105109937