CountDownLatch, CyclicBarrier和Semaphore

CountDownLatch

Description:
A synchronization auxiliary class that allows one or more threads to wait forever before completing a set of operations being performed in other threads.
API brief

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

application

  // 创建一个默认计数为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

Similar to CountDownLatch, but it can be used cyclically, which is equivalent to a valve. If the number of waiting threads reaches this threshold, all waiting threads will be released, and then recalculated.
Official explanation: Allow a group of threads to wait for each other to reach the common barrier point synchronization Auxiliary
countdownLatch is to release all waiting threads after the count is 0, CyclicBarrier is to release all waiting threads API after the number of waiting threads reaches the specified value

// 构造器, 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()

application

// 当等待的线程数到达设置的阈值的时候,执行回调函数,然后等待的线程继续执行
     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();

Output result

Execute the callback function. . .
Thread-2 starts execution 1!
Thread-1 starts to execute 1 to
execute the callback function. . .
Thread-1 starts execution 2
Thread-2 starts execution 2!

Semaphore

字面意思就是信号量,可以控制并发访问的线程数;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()
 

use

        // 创建一个有两个许可证的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();
        }

Output result, only 2 threads are executing per second

默认有2 个许可
1 == Thread-1
1 == Thread-9
2 == Thread-8
2 == Thread-5
3 == Thread-0
3 == Thread-6
4 == Thread-3
4 == Thread-2
5 == Thread-7
5 == Thread-4

Guess you like

Origin blog.csdn.net/xiaodujava/article/details/101529109