• java多线程系列(八)---CountDownLatch和CyclicBarrie


    CountDownLatch

    前言:如有不正确的地方,还望指正。

    目录

    什么是CountDownLatch

    • 允许一个或多个线程等待其他线程完成后再执行,比如说我们要等待人齐了才一起吃饭

    核心方法

    • CountDownLatch(int count):构造方法,初始计数器
    • await():使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断
    • countDown():计数器减一
    • getCount():返回当前计数

    使用过程

    • CountDownLatch内部有一个线程数量计数器,当一个(或多个)线程执行await方法后等待,其他的线程完成任务后,计数器减一。如果此时计数器大于0,那么等待的线程继续等待。如果为0,表示其他线程任务执行完成,此时等待的线程会被唤醒

    CountDownLatch使用

    import java.util.concurrent.CountDownLatch;
    
    public class Demo {
    	public static void main(String[] args) {
    		CountDownLatch cd = new CountDownLatch(3);
    		EatThread et=new EatThread(cd);
    		PeopleComeThread father=new PeopleComeThread(cd,"father");
    		PeopleComeThread mother=new PeopleComeThread(cd,"mother");
    		PeopleComeThread son=new PeopleComeThread(cd,"son");
    		et.start();
    		father.start();
    		mother.start();
    		son.start();
    	}
    }
    class EatThread extends Thread
    {
    
    	CountDownLatch cd;
    	public EatThread(CountDownLatch cd)
    	{
    		this.cd=cd;
    	}
    	public void run()
    	{
    		System.out.println("等待人齐再吃饭");
    		try {
    			cd.await();
    		} catch (InterruptedException e) {
    			// TODO 自动生成的 catch 块
    			e.printStackTrace();
    		}
    		System.out.println("好了,人齐开饭");
    		
    	}
    }
    class PeopleComeThread extends Thread
    {
    	CountDownLatch cd;
    	String name;
    	public PeopleComeThread(CountDownLatch cd,String name)
    	{
    		this.cd=cd;
    		this.name=name;
    	}
    	public void run()
    	{
    		System.out.println(name+"即将到达");
    		try {
    			Thread.sleep(2000);
    		} catch (InterruptedException e) {
    			// TODO 自动生成的 catch 块
    			e.printStackTrace();
    		}
    		cd.countDown();
    	}
    }
    
    • 输出结果
    等待人齐再吃饭
    mother即将到达
    father即将到达
    son即将到达
    好了,人齐开饭
    
    • 代码中我们只用到一个CountDownLatch对象,并初始化了一个计数器,执行await的线程等待,当执行一次countDown后,计数器减一,计数器为0后,等待的线程被唤醒

    CyclicBarrier

    什么是CyclicBarrier

    • 它允许一组线程互相等待,直到到达某个公共屏障点 ,也就是说多个线程等待,达到一个点的时候唤醒。

    核心方法

    • CyclicBarrier(int parties),屏障(barrier)拦截的线程数,也就是parties个线程执行await方法后,这几个线程才能集体唤醒
    • CyclicBarrier(int parties, Runnable barrierAction),barrierAction到达屏障后执行的任务

    使用过程

    • 同样是内部有一个计数器,初始化拦截的线程数,每一个线程执行awiat,计数器就会减一,当计数器为0的时候说明到达屏障,线程唤醒

    CyclicBarrier使用

    import java.util.concurrent.BrokenBarrierException;
    import java.util.concurrent.CyclicBarrier;
    
    public class Demo2 {
    	public static void main(String[] args) {
    		CyclicBarrier cb=new CyclicBarrier(3);
    		PeopleComeThread father=new PeopleComeThread(cb,"father");
    		PeopleComeThread mother=new PeopleComeThread(cb,"mother");
    		PeopleComeThread son=new PeopleComeThread(cb,"son");
    		father.start();
    		mother.start();
    		son.start();
    	}
    }
    class PeopleComeThread extends Thread
    {
    	CyclicBarrier cb;
    	String name;
    	public PeopleComeThread(CyclicBarrier cb,String name)
    	{
    		this.cb=cb;
    		this.name=name;
    	}
    	public void run()
    	{
    		System.out.println(name+"等待其他人到齐,等到3个人都到齐就可以吃饭");
    		try {
    			cb.await();
    		} catch (InterruptedException e) {
    			// TODO 自动生成的 catch 块
    			e.printStackTrace();
    		} catch (BrokenBarrierException e) {
    			// TODO 自动生成的 catch 块
    			e.printStackTrace();
    		}
    		System.out.println("人齐了,"+name+"开始吃饭");
    	}
    }
    
    • 输出结果
    mother等待其他人到齐,等到3个人都到齐就可以吃饭
    father等待其他人到齐,等到3个人都到齐就可以吃饭
    son等待其他人到齐,等到3个人都到齐就可以吃饭
    人齐了,son开始吃饭
    人齐了,mother开始吃饭
    人齐了,father开始吃饭
    
    
    • 代码中我们用到了CyclicBarrier对象,并给他初始化拦截的线程数为n,执行await的线程等待,当n个线程都执行await方法后,这n个线程唤醒

    比较

    • 两者都是一种消息等待通知机制,目的都是解决什么时候让等待的线程的唤醒
    • CountDownLatch不能重置计数,CyclicBarrier可以

    我觉得分享是一种精神,分享是我的乐趣所在,不是说我觉得我讲得一定是对的,我讲得可能很多是不对的,但是我希望我讲的东西是我人生的体验和思考,是给很多人反思,也许给你一秒钟、半秒钟,哪怕说一句话有点道理,引发自己内心的感触,这就是我最大的价值。(这是我喜欢的一句话,也是我写博客的初衷)

    作者:jiajun 出处: http://www.cnblogs.com/-new/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。如果觉得还有帮助的话,可以点一下右下角的【推荐】,希望能够持续的为大家带来好的技术文章!想跟我一起进步么?那就【关注】我吧。

  • 相关阅读:
    深入理解Java虚拟机二之Java内存区域与内存溢出异常
    深入理解java虚拟机一之走进Java
    数据结构之链表
    Spring AOP 详解
    Spring IOC 注入方式详解 附代码
    图的广度优先遍历
    图的深度优先遍历
    MySql 中的<=>操作符
    mysql数据库explain命令用法详解
    Java虚拟机内存分配详解
  • 原文地址:https://www.cnblogs.com/-new/p/7401360.html
Copyright © 2020-2023  润新知