JUC辅助类-CountDownLatch、CyclicBarrier、Semaphore

55 阅读2分钟

CountDownLatch

CountDownLatch类可以设置一个计数器,然后通过countdown方法来进行减的操作,使用await方法等待计数器不大于,然后继续执行await方法之后的语句。

  • CountDownLatch主要有两个方法,当一个或多个线程调用await方法时,这些线程会阻塞
  • 其他线程调用countDown方法会将计数器减(调用countDown方法的线程不会阻塞)
  • 当计数器的值变为0时,因await方法会阻塞的线程会被唤醒,继续执行。
// 演示 CountDownLatch
public class countDownLatchDemo {
    // 6个同学离开才能锁门
    public static void main(String[] args) throws InterruptedException {
        // 创建countdownlatch
        CountDownLatch countDownLatch = new CountDownLatch(6);
        // 6个同学陆续离开
        for (int i = 0; i < 6; i++) {
            new Thread(()->{
                System.out.println(Thread.currentThread().getName()+"号 离开了教室!");
                countDownLatch.countDown();
            },String.valueOf(i)).start();
        }
        countDownLatch.await();
        System.out.println(Thread.currentThread().getName()+"锁门走人");
    }

}

image.png

CyclicBarrier

CyclicBarrier 看英文单词就可以看出大概就是循环阻塞的意思,在使用中CyclicBarrier的构造方法的第一个参数就是目标障碍数,执行CyclicBarrier一次障碍数就会加一,如果达到目标障碍数,才会执行cyclicbarrier.await()之后的语句

例如:集齐七颗龙珠可以召唤神龙

public class CyclicbarrierDemo {
    //创建固定值
    private static final int NUMBER = 7;
    public static void main(String[] args) {
        //创建ciclicbarrier
        CyclicBarrier cyclicBarrier = new CyclicBarrier(NUMBER, () -> {
            System.out.println("******* 龙珠再现");
        });

        // 集齐七颗龙珠过程
        for (int i = 0; i < 7; i++) {
            new Thread(()->{
                System.out.println(Thread.currentThread().getName()+"星龙被收集到了");
                //等待
                try {
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                } catch (BrokenBarrierException e) {
                    throw new RuntimeException(e);
                }
            },String.valueOf(i)).start();
        }
    }
}

image.png

image.png

Semaphore

一个计数的信号量。从概念上讲,信号量维护了一个许可集。如有必要,在许可可用前会阻塞每一个acquire(),然后再获取该许可。每个release()添加一个许可,从而可能释放一个正在阻塞的获取值。但是,不使用实际的许可对象,Semaphore只对可用许可的号码进行技术,并采取相应的措施。

6辆车停三个停车位

// 6 辆车 三个停车位
public class SemaphoreDemo {
   public static void main(String[] args) {
       //创建semaphore 设置许可数量
       Semaphore semaphore = new Semaphore(3);

       // 模拟6辆汽车
       for (int i = 0; i < 6; i++) {
           new Thread(()->{
               //抢占
               try {
                   semaphore.acquire();

                   System.out.println(Thread.currentThread().getName()+"抢到了车位!");

                   // 设置随机停车时间
                   TimeUnit.SECONDS.sleep(new Random().nextInt(5));

                   System.out.println(Thread.currentThread().getName()+"离开了车位!");
               }catch (Exception e){
                   e.printStackTrace();
               }finally {
                   semaphore.release();
               }
           },String.valueOf(i)).start();
       }
   }
}

image.png