CountDownLatch和CylicBarrier以及Semaphare你使用过吗

Stella981
• 阅读 881

#CountDownLatch ###是什么 CountDownLatch的字面意思:倒计时 门栓 它的功能是:让一些线程阻塞直到另一些线程完成一系列操作后才唤醒。 它通过调用await方法让线程进入阻塞状态等待倒计时0时唤醒。 它通过线程调用countDown方法让倒计时中的计数器减去1,当计数器为0时,会唤醒哪些因为调用了await而阻塞的线程。

  • 底层是使用AQS实现的

###案例 假设老板开一个紧急会议,他先到会议室等着所有人签到然后开始开会,可以使用CountDownLatch进行模拟。

 public static void main(String[] args) {
        CountDownLatch countDownLatch=new CountDownLatch(5);

        for (int i=1;i<=5;i++){
            new Thread(()->{
                System.out.println(Thread.currentThread().getName()+"签到!");
                countDownLatch.countDown();
            },"第"+i+"個人").start();
        }


        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("老板宣布人夠了开始开会!");
    }

运行结果:

//注意这里的签到顺序可以随意
第1個人签到!
第2個人签到!
第3個人签到!
第4個人签到!
第5個人签到!
老板宣布人夠了开始开会!

#CyclicBarrier ###是什么 CyclicBarrier [ˈsaɪklɪk] [ˈbæriər] 的字面意思:可循环使用的屏障 【栅栏】 它的功能是:让一组线程到达一个屏障时被阻塞,知道最后一个线程到达屏障,所有被屏障拦截的线程才会继续执行。 它通过调用await方法让线程进入屏障,

  • 底层是通过ReentrantLock以及Condition中的await和signal实现

    /** The lock for guarding barrier entry / private final ReentrantLock lock = new ReentrantLock(); /* Condition to wait on until tripped */ private final Condition trip = lock.newCondition();

###图例 CountDownLatch和CylicBarrier以及Semaphare你使用过吗

###例子 还是上面的开会的例子,我们使用CyclicBarrier实现。

public static void main(String[] args) {
        CyclicBarrier cyclicBarrier=new CyclicBarrier(5,()->{
            System.out.println("老板宣布人夠了开始开会!!");
        });

        for (int i=1;i<=5;i++){
            new Thread(()->{
                try {
                    System.out.println(Thread.currentThread().getName()+"签到!");
                    cyclicBarrier.await(); //如果等待的线程数未到,这里将一直等待
                    //等线程数够了下面语句将继续执行......
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            },"第"+i+"個人").start();
        }
    }

运行结果:

第1個人签到!
第2個人签到!
第3個人签到!
第4個人签到!
第5個人签到!
老板宣布人夠了开始开会!!

#Semaphor ###是什么 Semaphor [ˈseməfɔːr] 信号量的意思; 它主要用于两个目的:

  • 用于多个共享资源互斥使用。【也就是具有锁的功能】 一个停车场有多个停车位,这多个停车位对应汽车来说就是多个共享资源,Semaphor可以实现多个停车位和多个汽车之间的互斥。

  • 用于控制并发线程数。(就是控制同时得到共享资源的线程数量) 在创建Semaphor时可以指定并发线程数,

    //permits :允许
    public Semaphore(int permits) {
        sync = new NonfairSync(permits);
    }
    //还可以指定是否为公平锁
    public Semaphore(int permits, boolean fair) {
        sync = fair ? new FairSync(permits) : new NonfairSync(permits);
    }
    
  • 信号量为1时 相当于独占锁 信号量大于1时相当于共享锁。

###例子 我们测试使用Semaphor实现控制线程并发访问方法。

/**
 * 测试使用Semaphor信号量控制方法的访问
 */
public class TestSemaphor {
    Semaphore semaphore=new Semaphore(5);
    /**
     * 假设并发只能为5个
     */
    public void pay(){
        try {
            //在 semaphore.acquire() 和 semaphore.release()之间的代码,同一时刻只允许指定个数的线程进入!
            semaphore.acquire();
            System.out.println("这是支付的方法!");
            Thread.sleep(2000);
            semaphore.release();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

   public static void main(String[] args) {
        TestSemaphor ts=new TestSemaphor();
        for (int i=0;i<10;i++){
            new Thread(()->{
                ts.pay();
            },"线程"+i).start();
        }
    }
}

运行效果:

线程0这是支付的方法!
线程3这是支付的方法!
线程6这是支付的方法!
线程5这是支付的方法!
线程1这是支付的方法!

//注意这里是执行的暂停点

线程7这是支付的方法!
线程8这是支付的方法!
线程2这是支付的方法!
线程4这是支付的方法!
线程9这是支付的方法!

注意结果:10个线程分了两批执行的,也就是说我们控制了访问pay方法的线程数量,每次并发只能是5个!

#CountDownlatch和CyclicBarrier以及Semaphor的区别是

  • CountDownLatch是做减法,CyclicBarrier是做加法,Semaphor的临界资源可以反复使用

  • CountDownLatch不能重置计数,CycliBarrier提供的reset()方法可以重置计数,不过只能等到第一个计数结束。Semaphor可以重复使用。

  • CountDownLatch和CycliBarrier不能控制并发线程的数量,Semaphor可以实现控制并发线程的数量。

#资源 更好的介绍

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
java 线程篇 之CyclicBarrier、CountDownLatch、Semaphore
java提供了很多控制线程到达某一状态导致之前阻塞线程运行的函数,这些在控制任务执行提供了很大的便利,比如在zookper使用Semaphore实现分布式锁1、CountDownLatchcountDownLatch提供await(),CountDownLatch()来控制,前面我很多例子,使用这个来模拟多线程运行的,所以这里不过多介绍2
Wesley13 Wesley13
3年前
java并发编程之二
CountDownLatch类  允许一个或多个线程等待直到在其他线程中执行的一组操作完成的同步辅助。  CountDownLatch能够使一个线程在等待另外一些线程完成各自工作之后,再继续执行。使用一个计数器进行实现。计数器初始值为线程的数量。当每一个线程完成自己任务后,计数器的值就会减一。当计数器的值为0时,表示所有的线程都已经完成了任务,然后在
Wesley13 Wesley13
3年前
4、jstack查看线程栈信息
1、介绍利用jps、top、jstack命令找到进程中耗时最大的线程,以及线程状态等等,同时最后还可以显示出死锁的线程查找:FoundoneJavaleveldeadlock即可1、jps获得进程号!(https://oscimg.oschina.net/oscnet/da00a309fa6
Stella981 Stella981
3年前
CountDownLatch、CyclicBarrier 的对比
CountDownLatch、CyclicBarrier都可以用于:在多线程异步执行过程中,执行预定的流程后唤醒指定的线程进行相应的操作.区别:1,CountDownLatch唤醒过一次,就废弃了;CyclicBarrier可以重复之前的预定流程,反复唤醒。2,CountDownLatch可用于唤醒主线程,异步线程\任意线程,
Wesley13 Wesley13
3年前
Java多线程并发控制工具CountDownLatch,实现原理及案例
闭锁(CountDownLatch)是Java多线程并发中的一种同步器,它是JDK内置的同步器。通过它可以定义一个倒计数器,当倒计数器的值大于0时,所有调用await方法的线程都会等待。而调用countDown方法则可以让倒计数器的值减一,当倒计数器值为0时所有等待的线程都将继续往下执行。闭锁的主要应用场景是让某个或某些线程在某个运行节点上等待N个条件都
Wesley13 Wesley13
3年前
Java CyclicBarrier介绍
CyclicBarrier(周期障碍)类可以帮助同步,它允许一组线程等待整个线程组到达公共屏障点。CyclicBarrier是使用整型变量构造的,其确定组中的线程数。当一个线程到达屏障时(通过调用CyclicBarrier.await()),它会被阻塞,直到所有线程都到达屏障,然后在该点允许所有线程继续执行。与CountDownLatch不同的
Wesley13 Wesley13
3年前
Java并发新构件之CounDownLatch
    CountDownLatch主要用于同步一个或多个任务,强制它们等待由其他任务执行的一组操作完成。    你可以向CountDownLatch对象设置一个初始计数值,任何在这个对象上调用await()的方法都将阻塞,直到这个计数值达到0。其他任务在结束其工作时,可以在该对象上调用countDown()来减小这个计数值,你可以通过调用get