1.CountDownLatch基础概念和使用

2.CyclicBarrier基础概念和使用

3.Semaphore基础概念和使用

1.CountDownLatch基础概念和使用
通俗的来说,CountDownLatch的功能就是让一些线程等待直到另外的一些线程全部运行结束之后,再开始运行
举个例子:
一个教室每天都要安排一个同学值日关门,这个同学一定要等到其他同学全部离开之后(等待其它线程全部执行完毕),才能把门关上(才会往下执行)。

我们用代码来证明一下上述的例子:

首先,我们要用到三个重要的方法:

//构造方法的数字表示,要等五个线程运行完毕后,才会继续往下执行
CountDownLatch countDownLatch = new CountDownLatch(5);
//需要等待的线程减一(相当于一个同学离开了教师)
countDownLatch.countDown();
//等待其它所有线程执行完毕,再往下执行(再往下执行关门动作)
countDownLatch.await();
    CountDownLatch countDownLatch = new CountDownLatch(5);

        for (int i = 1; i <= 5; i++) {
            new Thread(() -> {
                System.out.println("第" + Thread.currentThread().getName() + "个同学离开教室");
                //一个同学离开后,需要等待的线程就减一
                countDownLatch.countDown();
            }, i + "").start();
        }

        //到这儿等待
        countDownLatch.await();

        new Thread(() -> {
            System.out.println("班长离开教室");
        }).start();

执行结果为:
image.png

可以看出,countDownLatch等待其它线程执行完毕做的是减法操作。

2.CyclicBarrier基础概念和使用
如果说countDownLatch是做减法,CyclicBarrier就是做加法。
举个例子:集齐七颗龙珠召唤神龙!(等待七个线程运行完毕,然后执行最终的线程。)

同样地我们要用到两个方法:

        //构造函数可以传指定线程的数量,以及线程数量到达后的完成方法,可用lambda表达式完成。
        CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> {
            System.out.println("召唤神龙!");
        });
        //当一个线程执行完毕后,调用这个方法表示已经执行的线程+1(已收集的龙珠+1)
        cyclicBarrier.await();

我们将举例用代码实现一次:

       //设置等待的线程总数和完成之后的方法内容
       CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> {
            System.out.println("召唤神龙!");
        });

        for (int i = 1; i <= 7; i++) {
            final int num = i;
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "收集到第" + num + "颗龙珠");
                try {
                   //完成线程数+1
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }, i + "").start();
        }

运行结果为:
image.png

可以得出,CyclicBarrier是一个做加法的操作,线程增加到一定程度,就可以执行最终的线程。(就好像人到齐了再开会。)

3.Semaphore基础概念和使用
Semaphore是一种信号量,我们可以用“抢车位”来形容这个类,就像多辆车竞争多个车位。(多个线程争抢多个资源。)

我们仍然用代码来完成上面的举例:

//一共有三个资源
Semaphore semaphonre = new Semaphore(3);
//获得资源
semaphonre.acquire();
//释放资源
semaphonre.release();
        Semaphore semaphonre = new Semaphore(3);

        for (int i = 1; i <= 5; i++) {
            final int temp = i;
            new Thread(() -> {
                try {
                    semaphonre.acquire();
                    System.out.println("第" + temp + "辆车进入停车位");
                    Thread.sleep(3000);
                    System.out.println("第" + temp + "辆车,停车3秒后离开车位");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    semaphonre.release();
                }

            }, i + "").start();
        }

运行结果为:
image.png
可以看出,每次最多只能有三个停车位进入,否则就阻塞。

总结:
CountDownLatch:做减法,当计数器变为0的时候,调用await的线程会被唤醒,继续执行。
CyclicBarrier:做加法,等到一定数量的线程执行,再继续执行最终的方法。
Semaphore:多个线程争抢多个资源。


苏凌峰
73 声望38 粉丝

你的迷惑在于想得太多而书读的太少。