JUC并发编程快速入门篇(六)—— 三大辅助类

三大辅助类

少计数 CountDownLatch

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

  • CountDownLatch 主要有两个方法,当一个或多个线程调用 await 方法时,这些线程会阻塞

  • 其它线程调用 countDown 方法会将计数器减 1(调用 countDown 方法的线程不会阻塞)

  • 当计数器的值变为 0 时,因 await 方法阻塞的线程会被唤醒,继续执行

案例

//7位同学都离开教室,班长锁门
public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {

        CountDownLatch countDownLatch = new CountDownLatch(6);
        
        for (int i = 1; i <= countDownLatch.getCount(); i++) {
            new Thread(()->{
                System.out.println(Thread.currentThread().getName()+" 号同学离开教室");
                countDownLatch.countDown(); //计数器减1
            }).start();
        }

        countDownLatch.await(); //计数器不为0的时候继续等待
        System.out.println(Thread.currentThread().getName()+" 班长锁门");
    }
}

循环栅栏 CyclicBarrier

允许一组线程全部等待彼此达到共同屏障点的同步辅助。 循环阻塞在涉及固定大小的线程方的程序中很有用,这些线程必须偶尔等待彼此。 屏障被称为循环 ,因为它可以在等待的线程被释放之后重新使用。

举个例子,就像生活中我们会约朋友们到某个餐厅一起吃饭,有些朋友可能会早到,有些朋友可能会晚到,但是这个餐厅规定必须等到所有人到齐之后才会让我们进去。这里的朋友们就是各个线程,餐厅就是 CyclicBarrier。

CyclicBarrier 的构造方法第一个参数是目标障碍数,每次执行 CyclicBarrier 一次障碍数会加一,如果达到了目标障碍数,才会执行 cyclicBarrier.await()之后的语句。可以将 CyclicBarrier 理解为加 1 操作

案例

//集齐7颗龙珠召唤神龙
public class CyclicBarrierDemo {
    //创建固定值
    private static final int NUMBER = 7;

    public static void main(String[] args) {
        //创建CyclicBarrier
        CyclicBarrier cyclicBarrier = new CyclicBarrier(NUMBER,()->{
            System.out.println("***集齐7颗龙珠召唤神龙***");
        });
        //集齐7颗龙珠
        for (int i = 1; i <=7 ; i++) {
            new Thread(()->{
                try {
                    System.out.println(Thread.currentThread().getName()+" 星龙珠");
                    cyclicBarrier.await();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            },String.valueOf(i)).start();
        }
    }

}

信号量机制 Semaphore

Semaphore 的构造方法中传入的第一个参数是最大信号量(可以看成最大线程池),每个信号量初始化为一个最多只能分发一个许可证。使用 acquire 方法获得许可证,release 方法释放许可

//6辆汽车,3个停车位
public class SemaphoreDemo {
    public static void main(String[] args) {
        //创建semaphore
        Semaphore semaphore = new Semaphore(3);

        //模拟6辆汽车
        for (int i = 1; i <=6 ; i++) {
            new Thread(()->{
                try {
                    semaphore.acquire();
                    System.out.println("第"+Thread.currentThread().getName()+" 汽车抢得车位");
                    TimeUnit.SECONDS.sleep(5);//设置5秒离开车位
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    semaphore.release();
                    System.out.println("====第"+Thread.currentThread().getName()+"离开了车位====");
                }
            },String.valueOf(i)).start();
        }
    }
}
上一篇:CyclicBarrier及其用法详解


下一篇:CyclicBarrier 的使用与源码解析