Java并发编程小总结:CountDownLatch、CyclicBarrier和Semaphore

Java并发编程小总结:CountDownLatch、CyclicBarrier和Semaphore
这几个类都是在JUC下,也就是java.util.concurrent包下。
这两天学习了一下并发编程中的三个类的使用和一些应用场景,所以做一下记录和总结,方便自己日后再查看复现。

1、CountDownLatch。
这个类的核心思想总结为8个字“秦灭6国,一统华夏”。它可以实现的是一个类似计数器的功能,与CyclicBarrier的思想正好相反。是一个减法操作。
CountDownLatch有且只有一个构造器,且默认提供此构造器,设置初始值的时候必须大于0,否则就会抛异常,可看源码图。

public void await() throws InterruptedException { }; //调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行。此方法的位置在真正执行任务之前。
public boolean await(long timeout, TimeUnit unit) throws InterruptedException { }; //和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行。此方法的位置在真正执行任务之前。
public void countDown() { }; //每次线程执行完一次操作后可以将count值减1。如我们例子中灭掉一个国家就执行一次操作--。
public long getCount() {return sync.getCount();} //返回当前计数。

当秦要实现一统华夏的目的,必须把所有的6国都得全部的灭掉之后才可以统一。实行的是一个减法操作。

public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {

        CountDownLatch countDownLatch = new CountDownLatch(6);
        long count = countDownLatch.getCount();
        System.out.println(count);
        for (int i = 1; i <= 6; i++) {
            new Thread(() ->{
                System.out.println(Thread.currentThread().getName() + "\t 国,被干掉");
                countDownLatch.countDown();
            }, CountryEnum.forEach_countryEnum(i).getCountry()).start();
        }
        countDownLatch.await();
        System.out.println(" "+ Thread.currentThread().getName() + "\t*************秦帝国,一统华夏");
    }
}

执行结果:

6
齐 国,被干掉
楚 国,被干掉
燕 国,被干掉
秦 国,被干掉
韩 国,被干掉
魏 国,被干掉
main *************秦帝国,一统华夏

2、CyclicBarrier。
这个类的核心思想也总结为8个字“集齐龙珠,召唤神龙”,与CountDownLatch的思想正好相反,是一个加法操作。
CountDownLatch的计数器只能使用一次。而CyclicBarrier的计数器可以使用reset() 方法重置。所以CyclicBarrier能处理更为复杂的业务场景,比如如果计算发生错误,可以重置计数器,并让线程们重新执行一次。
CyclicBarrier的构造器设置的时候初始值也必须大于0。
参数barrierAction为当这些线程都达到barrier状态时会执行的内容。

public int await() throws InterruptedException, BrokenBarrierException { };// 调用await()方法的线程会被挂起,直到所有线程都达到状态时才会执行的任务。
public int await(long timeout, TimeUnit unit)throws InterruptedException,BrokenBarrierException,TimeoutException { };//和await()类似,只不过等待一定时间后还有线程未达到状态也不管了,直接执行任务。
有一个reset方法,可以重置计数。还有一些方法暂未被关注。
当要实现召唤神龙的目的,必须把7颗龙珠都集齐才可以执行。实行的是一个加法操作。

public class CyclicBarrierDemo {
    public static void main(String[] args) {

        CyclicBarrier cyclicBarrier = new CyclicBarrier(7,() ->{
            System.out.println("龙珠已经集齐,开始召唤神龙啦******************");
        });
        cyclicBarrier.reset();
        for (int i = 1; i <= 7; i++) {
            int finalI = i;
            new Thread(() ->{
                System.out.println("获得第" + finalI + "颗龙珠");
                try {
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }

            }).start();
        }
    }
}

执行结果:

获得第1颗龙珠
获得第5颗龙珠
获得第4颗龙珠
获得第3颗龙珠
获得第2颗龙珠
获得第6颗龙珠
获得第7颗龙珠
龙珠已经集齐,开始召唤神龙啦******************

3、Semaphore
这个类翻译过来叫做 信号量 ,可以通俗的理解为一个阻塞队列,只是可以控制同时进入的线程数。通过 acquire() 获取资格,如果没有就等待,当获取到资格执行完任务后可以 release() 退出资格。
Semaphore提供了2个构造器,//参数permits表示许可数目,即同时可以允许多少线程进行访问。//参数fair表示是否是公平的,不会的请自行百度公平和非公平锁。

public void acquire() throws InterruptedException { } //获取一个资格
public void acquire(int permits) throws InterruptedException { } //获取某个指定的资格
public void release() { } //释放当前资格
public void release(int permits) { } //释放指定的资格

这4个方法获取不到都会阻塞,直到获取成功为止。如果想要立刻直到结果可以使用tryAcquire()方法来确认。
public boolean tryAcquire() { }; //尝试获取一个资格,若获取成功,则立即返回true,否则立即返回false
public boolean tryAcquire(long timeout, TimeUnit unit) throws InterruptedException { }; //尝试获取一个资格,增加了一个超时功能,在指定时间内获得则立即返回true,否则则立即返回false
public boolean tryAcquire(int permits) { }; //尝试获取指定的资格,若获取成功,则立即返回true,否则立即返回false
public boolean tryAcquire(int permits, long timeout, TimeUnit unit) throws InterruptedException { }; //尝试获取指定资格,增加了一个超时功能,若在指定的时间内获取成功则立即返回true,否则则立即返回false
通过availablePermits()方法得到可用的许可数目。

public class SemaphoreDemo {

    public static void main(String[] args) {

        Semaphore semaphore = new Semaphore(5);

        for (int i = 1; i <= 8; i++) {
            int finalI = i;
            new Thread(() ->{
                try {
                    semaphore.acquire();
                    System.out.println(finalI +"--号工人进来使用机器");
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    System.out.println(finalI +"号工人退出使用机器--");
                    semaphore.release();
                }
            }).start();
        }
    }
}

执行结果:

2--号工人进来使用机器
4--号工人进来使用机器
1--号工人进来使用机器
3--号工人进来使用机器
5--号工人进来使用机器
5号工人退出使用机器--
3号工人退出使用机器--
4号工人退出使用机器--
8--号工人进来使用机器
2号工人退出使用机器--
1号工人退出使用机器--
7--号工人进来使用机器
6--号工人进来使用机器
8号工人退出使用机器--
6号工人退出使用机器--
7号工人退出使用机器--

-----------------------------------------------------------------------------------------------------------------------------------------------------

下面对上面说的三个辅助类进行一个总结:

  1)CountDownLatch和CyclicBarrier都能够实现线程之间的等待,只不过它们侧重点不同:

    CountDownLatch一般用于某个线程A等待若干个其他线程执行完任务之后,它才执行;

    而CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行;

    另外,CountDownLatch是不能够重用的,而CyclicBarrier是可以重用的。

  2)Semaphore其实和锁有点类似,它一般用于控制对某组资源的访问权限。

这里是参考博主-Matrix海子 大神的case https://www.cnblogs.com/dolphin0520/p/3920397.html
及观看 机构《尚硅谷》阳哥视频,做的小总结。

原文地址:https://www.cnblogs.com/shijianhenjinpo/p/12222547.html

时间: 2024-10-07 09:37:39

Java并发编程小总结:CountDownLatch、CyclicBarrier和Semaphore的相关文章

Java 并发编程中的 CountDownLatch 锁用于多个线程同时开始运行或主线程等待子线程结束

Java 5 开始引入的 Concurrent 并发软件包里面的 CountDownLatch 其实可以把它看作一个计数器,只不过这个计数器的操作是原子操作,同时只能有一个线程去操作这个计数器,也就是同时只能有一个线程去减这个计数器里面的值.CountDownLatch的一个非常典型的应用场景是:有一个任务想要往下执行,但必须要等到其他的任务执行完毕后才可以继续往下执行.假如我们这个想要继续往下执行的任务调用一个CountDownLatch对象的await()方法,其他的任务执行完自己的任务后调

Java并发编程:CountDownLatch、CyclicBarrier和Semaphore

在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch,CyclicBarrier和Semaphore,今天我们就来学习一下这三个辅助类的用法. 以下是本文目录大纲: 一.CountDownLatch用法 二.CyclicBarrier用法 三.Semaphore用法 若有不正之处请多多谅解,并欢迎批评指正. 请尊重作者劳动成果,转载请标明原文链接: http://www.cnblogs.com/dolphin0520/p/3920397.htm

java并发编程中CountDownLatch和CyclicBarrier的使用

转自:http://blog.csdn.net/hbzyaxiu520/article/details/6183714 在多线程程序设计中,经常会遇到一个线程等待一个或多个线程的场景,遇到这样的场景应该如何解决? 如果是一个线程等待一个线程,则可以通过await()和notify()来实现: 如果是一个线程等待多个线程,则就可以使用CountDownLatch和CyclicBarrier来实现比较好的控制. 下面来详细描述下CountDownLatch的应用场景: 例如:百米赛跑:8名运动员同时

Java并发编程:CountDownLatch、CyclicBarrier和Semaphore (总结)

下面对上面说的三个辅助类进行一个总结: 1)CountDownLatch和CyclicBarrier都能够实现线程之间的等待,只不过它们侧重点不同: CountDownLatch一般用于某个线程A等待若干个其他线程执行完任务之后,它才执行: 而CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行: 另外,CountDownLatch是不能够重用的,而CyclicBarrier是可以重用的. 2)Semaphore其实和锁有点类似,它一般用于控制对某组资源的访问权

Java并发编程:CountDownLatch、CyclicBarrier和 Semaphore

在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch,CyclicBarrier和Semaphore,今天我们就来学习一下这三个辅助类的用法. 以下是本文目录大纲: 一.CountDownLatch用法 二.CyclicBarrier用法 三.Semaphore用法 一.CountDownLatch用法 CountDownLatch类位于java.util.concurrent包下,利用它可以实现类似计数器的功能.比如有一个任务A,它要等待其他

【Java并发编程实战】—–“J.U.C”:CountDownlatch

上篇博文([Java并发编程实战]-–"J.U.C":CyclicBarrier)LZ介绍了CyclicBarrier.CyclicBarrier所描述的是"允许一组线程互相等待,直到到达某个公共屏障点,才会进行后续任务".而CountDownlatch和它也有一点点相似之处:CountDownlatch所描述的是"在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待".在JDK API中是这样阐述的: 用给定的计数 初始化 Co

【Java并发编程实战】—–“J.U.C”:CyclicBarrier

在上篇博客([Java并发编程实战]-–"J.U.C":Semaphore)中,LZ介绍了Semaphore,下面LZ介绍CyclicBarrier.在JDK API中是这么介绍的: 一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point).在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用.因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier. Cy

Java并发编程之-了解CyclicBarrier

起因:一道面试题,关于concurrent包下的CyclicBarrier并发工具类,提出的一个情景题,因为不了解,所以花了一天的时间去学习并以此记录而诞生的这篇博客. 题目:假设有5个运动员(线程),让他们就绪在同一位置开始比赛跑步,当裁判(主线程)发出枪响号令.5个运动员(5个线程执行)开始奔跑,当5个线程跑到终点后.裁判(主线程执行)宣布比赛结果. 知识点:CyclicBarrier,CountDownLatch这两个位于JDK concurren包下的两个类.今天只实现CyclicBar

JAVA并发编程J.U.C学习总结

前言 学习了一段时间J.U.C,打算做个小结,个人感觉总结还是非常重要,要不然总感觉知识点零零散散的. 有错误也欢迎指正,大家共同进步: 另外,转载请注明链接,写篇文章不容易啊,http://www.cnblogs.com/chenpi/p/5614290.html 本文目录如下,基本上涵盖了J.U.C的主要内容: JSR 166及J.U.C Executor框架(线程池. Callable .Future) AbstractQueuedSynchronizer(AQS框架) Locks & C