Java面试题(十二) 面试官:“小伙子,CountDownLatch/CyclicBarrier/Semaphore使用过吗?”

一. CountDownLatch

CountDownLatch:
他允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行。

他是线程一直减减的

CountDownLatch主要有两个方法,
    1.当一个或多个线程调用await()方法时,调用线程会被阻塞。
    2.其他线程调用countDown()方法会将计数器减1,当计数器的值变为0时,
      因调用await()方法被阻塞的线程才会被唤醒,继续执行

案例:饭店吃饭

public static void main(String[] args) throws Exception {

        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 ##老板,关门回家");

    }

运行结果
在这里插入图片描述
总结:

适用于,要先完成某些前置任务,才会触发后续任务的案例。

二. CyclicBarrier

CyclicBarrier:
可循环(Cyclic)使用的屏障。
让一组线程到达一个屏障(也可叫同步点)时被阻塞,
直到最后一个线程到达屏障时,屏障才会开门,
所有被屏障拦截的线程才会继续干活,线程进入屏障通过CycliBarrier的await()方法

他是线程一直加加的

案例:收集七龙珠,召唤神龙。

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:
	信号量主要用于两个目的,一个是用于多个共享资源的互斥作用,
	另一个用于并发线程数的控制

适用于秒杀,小米秒杀手机使用Semaphore。

可以代替 Synchronize 和 Lock

案例:抢车位

public static void main(String[] args) {

        Semaphore semaphore = new Semaphore(3); //模拟3个停车位

        //6辆车抢车位
        for (int i = 1; i <= 6; i++) {

            new Thread(() -> {
                try {
                    //抢占车位
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName() + "### 抢到车位");
                    try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
                    System.out.println(Thread.currentThread().getName() + "### 停车3秒后离开车位");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    //释放车位
                    semaphore.release();
                }
            }, String.valueOf(i)).start();
        }
    }

运行结果
在这里插入图片描述
总结:

适用于,秒杀等,一些需要多线程抢占多线程的任务。

猜你喜欢

转载自blog.csdn.net/w_x_A__l__l/article/details/106882149
今日推荐