JUC辅助类专题

152 阅读2分钟

一、CountDownLatch--减少计数

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

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

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

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

使用场景:6个同学陆续离开教室后值班同学才可以关门

public class CountDownLatchDemo{
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch cdl = new CountDownLatch(6);

        System.out.println("主线程休眠了");
        for (int i = 1; i <= 6; i++) {
            new Thread(()->{
                if (Thread.currentThread().getName().equals("线程6")){
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(Thread.currentThread().getName() + "离开了");
                cdl.countDown();
            },"线程" + i).start();
        }

        cdl.await();
        System.out.println("全部离开了,现在计数器为" + cdl.getCount());
    }
}

二、CyclicBarrier--循环栅栏

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

使用场景:集齐7颗龙珠就可以召唤神龙

public class CyclicBarrierDemo{
    private static final int NUM = 7;

    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(NUM,()->{
            System.out.println("收集" + NUM + "完成,召唤神龙许愿");
        });

        for (int i = 1; i <= 7; i++) {
            new Thread(()->{
                System.out.println("争抢" + Thread.currentThread().getName() + "开始");
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("争抢" + Thread.currentThread().getName() + "结束");
                try {
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            },"龙珠" + i + "号").start();
        }
    }
}

三、Semaphore--信号灯

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

使用场景:抢车位,6辆车3个车位

public class SemaphoreDemo {
    public static void main(String[] args) throws InterruptedException {
        Semaphore semaphore = new Semaphore(3);

        for (int i = 1; i <= 6; i++) {
            Thread.sleep(1000);
            //停车
            new Thread(() -> {
                try {
                    System.out.println(Thread.currentThread().getName() + "找车位ing");
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName() + "汽车停车成功!");
                    Thread.sleep(10000);
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    System.out.println(Thread.currentThread().getName() + "溜了溜了");
                    semaphore.release();
                }
            }, "汽车" + i).start();
        }
    }
}