CountDownLatch、CyclicBarrier和セマフォ

記事ディレクトリ

CountDownLatch

説明:
1つ以上のスレッドが、他のスレッドで実行されている一連の操作を完了する前に永久に待機できるようにする同期補助クラス。
APIブリーフ

// 构造器, 指定计数值的初始值
public CountDownLatch(int count)
// 使当前线程等待, 除非当前计数为0
public void await()
// 线程等待, 添加了个超时时间,如果超过了 设置的时间 及时计数不为0也继续执行
public boolean await(long timeout, TimeUnit unit)
// 计数减一
 public void countDown()

応用

  // 创建一个默认计数为1 的countDownLatch
        final CountDownLatch countDownLatch = new CountDownLatch(1);

        new Thread(() -> {
    
    
            try {
    
    
                // 线程等待 countDownLatch计数为0
                countDownLatch.await();
            System.out.println(Thread.currentThread().getName() + " 在执行   countDownLatch.await();");
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
        }).start();

        new Thread(() -> {
    
    
            try {
    
    
            System.out.println(Thread.currentThread().getName() + " 在执行   countDownLatch.countDown();");
                TimeUnit.SECONDS.sleep(1);
                // 计数减一
                countDownLatch.countDown();
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
        }).start();

CyclicBarrier

CountDownLatchに似ていますが、バルブと同等の循環的に使用できます。待機中のスレッドの数がこのしきい値に達すると、すべての待機中のスレッドが解放されてから再計算されます。
公式の説明:スレッドのグループが待機できるようにします。共通のバリアポイント同期に到達するために相互に補助
countdownLatchは、カウントが0になった後にすべての待機中のスレッドを解放し、CyclicBarrierは待機中のスレッドの数が指定された値に達した後にすべての待機中のスレッドを解放し
ます。API

// 构造器, parties 线程等待数阈值
 public CyclicBarrier(int parties)
 // 构造器,parties 线程等待数阈值, barrierAction 当屏障数到达阈值后执行的回调函数
public CyclicBarrier(int parties, Runnable barrierAction)
// await() 线程等待
 public int await() throws InterruptedException, BrokenBarrierException 
 // 带有等待超时时间的await
  public int await(long timeout, TimeUnit unit)
// 重置阈值从新计算, 如果有线程在等待则抛异常java.util.concurrent.BrokenBarrierException
public void reset()

応用

// 当等待的线程数到达设置的阈值的时候,执行回调函数,然后等待的线程继续执行
     final CyclicBarrier cyclicBarrier = new CyclicBarrier(2,
                new Thread(()-> {
    
    
                    System.out.println("执行回调函数。。。");
                }));
        new Thread(() -> {
    
    
            try {
    
    
            // 线程第一次等待
                cyclicBarrier.await();
            System.out.println(Thread.currentThread().getName() +" 开始执行1");
            // 线程第二次等待
                cyclicBarrier.await();
            System.out.println(Thread.currentThread().getName() +" 开始执行2");
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
    
    
                e.printStackTrace();
            }
        }).start();
        new Thread(() -> {
    
    
            try {
    
    
                cyclicBarrier.await();
                System.out.println(Thread.currentThread().getName() +" 开始执行1!");
                cyclicBarrier.await();
                System.out.println(Thread.currentThread().getName() +" 开始执行2!");
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
    
    
                e.printStackTrace();
            }
        }).start();

出力結果

コールバック関数を実行します。
スレッド2が実行1を開始します!
スレッド1は
、コールバック関数実行するために1の実行を開始します。
スレッド1が実行2を開始します
スレッド2が実行2を開始します!

セマフォ

字面意思就是信号量,可以控制并发访问的线程数;Semaphore可以用于做流量控制

API

// 创建一个指定数量许可的Semaphore
public Semaphore(int permits)
// fair 是否公平
public Semaphore(int permits, boolean fair)
// 获取一个许可, 如果获取不到则阻塞
public void acquire() throws InterruptedException 
// 尝试获取一个许可,获取到返回true, 获取不到返回false
public boolean tryAcquire() 
// 在指定时间内尝试获取一个许可
public boolean tryAcquire(long timeout, TimeUnit unit)
// 释放一个许可
public void release() 
//释放多个许可
public void release(int permits)

//返回此信号量中可用的许可证的当前数量。
public int availablePermits() 

//获取并返回所有可用的许可, 此方法会消耗掉所有的可用许可
public int drainPermits()
 

使用する

        // 创建一个有两个许可证的Semaphore
        final Semaphore semaphore = new Semaphore(2);
        System.out.println("默认有" + semaphore.availablePermits() + " 个许可");
        // 创建10 个线程执行
        for (int i = 0; i <10 ; i++) {
    
    
            new Thread(() -> {
    
    
                try {
    
    
                    // 获取一个许可
                    Stopwatch stopwatch = Stopwatch.createStarted();
                    semaphore.acquire();
                    TimeUnit.SECONDS.sleep(1);
                    System.out.println(stopwatch.elapsed(TimeUnit.SECONDS) +" == " + Thread.currentThread().getName());

                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                } finally {
    
    
                    // 释放一个许可
                    semaphore.release();
                }
            }).start();
        }

出力結果、1秒あたり2つのスレッドのみが実行されています

默认有2个许可
1 ==スレッド1
1 ==スレッド9
2 ==スレッド8
2 ==スレッド5
3 ==スレッド0
3 ==スレッド6
4 ==スレッド3
4 ==スレッド
-25 ==スレッド
-75 ==スレッド-4

おすすめ

転載: blog.csdn.net/xiaodujava/article/details/101529109