JUC辅助类

329 阅读2分钟

引言:更多相关请看 JAVA并发编程系列

CountDownLatch减少计数

含义:让一些线程阻塞直到另外一些完成后才被唤醒。
CountDownLatch主要有两个方法,当一个或多个线程调用await方法时,调用线程会被阻塞.其他线程调用countDown方法计数器减1(调用countDown方法时线程不会阻塞),当计数器的值变为0,因调用await方法被阻塞的线程会被唤醒,继续执行。

案例

class CountDownLatchDemo {
    public static void main(String[] args) throws Exception {
//        closeDoor();
        destroySixCountry();
    }

    /**
     * 关门案例
     * 班长必须等六位同学离开教室才能锁教室门
     * @throws InterruptedException
     */
    private static void closeDoor() throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(6);
        for (int i = 1; i <= 6; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "\t" + "上完自习");
                countDownLatch.countDown();
            }, String.valueOf(i)).start();
        }
        countDownLatch.await();
        System.out.println(Thread.currentThread().getName() + "\t班长锁门离开教室");
    }

    /**
     * 秦灭六国案例
     * 秦朝必须灭掉六国才能统一天下
     * @throws InterruptedException
     */
    private static void destroySixCountry() throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(6);
        for (int i = 1; i <= 6; i++) {
            final int temp = i;
            new Thread(() -> {
                System.out.println(CountryEnum.forEach(temp).getName() + "\t" + "被灭");
                countDownLatch.countDown();
            }, String.valueOf(i)).start();
        }
        countDownLatch.await();
        System.out.println(Thread.currentThread().getName() + "\t秦国统一天下");
    }
}

@Getter
@AllArgsConstructor
// @Data 不支持使用在枚举里面
enum CountryEnum {
    /**
     * 六国枚举
     */
    ONE(1, "齐"),TWO(2, "楚"),THREE(3, "燕"),FOUR(4, "赵"),FIVE(5, "魏"), SIX(6, "韩");

    private Integer code;
    private String name;

    public static CountryEnum forEach(int index) {
        CountryEnum[] countryEnums = CountryEnum.values();
        for (CountryEnum countryEnum : countryEnums) {
            if (index == countryEnum.getCode()) {
                return countryEnum;
            }
        }
        return null;
    }
}

CyclicBarrier循环栅栏

CyclicBarrier的字面意思是可循环(Cyclic)使用的屏障(barrier)。它要做的事情是,让一组线程到达一个屏障(也可以叫做同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活,线程进入屏障通过CyclicBarrier的await()方法。

案例

/**
 * 集齐7颗龙珠就能召唤神龙
 */
class CyclicBarrierDemo {
    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier=new CyclicBarrier(7,()->{
            System.out.println("召唤神龙");
        });
        for (int i = 1; i <=7; i++) {
            final int temp = i;
            new Thread(()->{
                System.out.println(Thread.currentThread().getName()+"\t 收集到第"+ temp +"颗龙珠");
                try {
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            },String.valueOf(i)).start();
        }


    }
}

效果:

Semaphore信号灯

信号灯的主要用户两个目的,一个是用于多个共享资源的相互排斥使用,另一个用于并发资源数的控制。 默认非公平锁。

案例

/**
 * 抢车位
 * Semaphore有两个方法,acquire获取和release释放
 */
class SemaphoreDemo {
    public static void main(String[] args) {
        // 同时最多只有3辆车能抢到车位,其它车辆必须等到有空闲车位时才能抢车位。
        //模拟3个停车位
        Semaphore semaphore = new Semaphore(3);
        //模拟8部汽车
        for (int i = 1; i <= 8; i++) {
            new Thread(() -> {
                try {
                    //抢到资源
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName() + "\t抢到车位");
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "\t 停0.5秒离开车位");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    //释放资源
                    semaphore.release();
                }
            }, String.valueOf(i)).start();
        }
    }
}

效果: