CountDownLatch, CyclicBarrier和Semaphore

CountDownLatch

描述:
一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。
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();

输出结果

执行回调函数。。。
Thread-2 开始执行1!
Thread-1 开始执行1
执行回调函数。。。
Thread-1 开始执行2
Thread-2 开始执行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()
 

运用

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

输出结果, 每秒只有2个线程在执行

默认有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

猜你喜欢

转载自blog.csdn.net/xiaodujava/article/details/101529109