CountDownLatch、CyclicBarrier、Semaphore

一、CountDownLatch - 闭锁/做减法

人都走了才关门

  • 使一个线程等待其他线程各自执行完毕后再执行;
  • 是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。
// 参数count为计数值
CountDownLatch countDownLatch = new CountDownLatch(6);
// 调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行
countDownLatch.await();
// 将count值减1
countDownLatch.countDown();
二、CyclicBarrier - 栅栏/屏障/做加法

人到齐了才开会/集齐七颗龙珠才能召唤神龙

  • 字面意思是可循环使用的屏障
  • 让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障才会开门,所有被屏障拦截的线程才会继续干活,当线程到达栅栏位置时将调用await方法。如果所有线程都到达栅栏位置,那么栅栏将打开,此时所有的线程都将被释放,而栅栏将被重置以便下次使用。
CyclicBarrier cyclicBarrier = new CyclicBarrier(7)// 屏障/栅栏同步点
cyclicBarrier.await();
四、CountDownLatch和CyclicBarrier区别
  • CountDownLatch是一个计数器,线程完成一个记录一个,计数器递减,只能只用一次,闭锁用于等待事件;
  • CyclicBarrier的计数器更像一个阀门,需要所有线程都到达,然后继续执行,计数器递增,提供reset功能,可以多次使用,栅栏用于等待其他线程
五、Semaphore 计数信号量/信号灯

争车位,30量车争20个车位

  • 计数信号量,必须由获取它的线程释放
  • 常用于限制可以访问某些资源的线程数量,例如通过 Semaphore 限流。
  • 有两个目的,第一个是多个共享资源互斥使用,第二个是并发线程数的控制
  • 信号量为多个线程协作提供了更强大的控制方法,无论是ReentrantLock还是Synchronized一次都只允许一个线程访问一个资源。信号量允许多个线程同时访问同一个资源。
// 3个车位
Semaphore semaphore = new Semaphore(3);

// 6量车
for (int i = 0; i <= 6; i++) {
    new Thread(() -> {
        try {
            // 获取锁资源
            semaphore.acquire();
            // 抢车位
            System.out.println(Thread.currentThread().getName() + "\t 抢到车位...");
            // 模拟车停靠时间
            TimeUnit.SECONDS.sleep(3);
            System.out.println(Thread.currentThread().getName() + "\t 停车3秒后离开车位...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            // 释放锁资源
            semaphore.release();
        }
    }, String.valueOf(i)).start();
}
posted @ 2019-09-07 17:51  要好好吃饭  阅读(134)  评论(0编辑  收藏  举报