Java中的CountDownLatch同步工具类使用解析

 更新时间:2023年12月16日 09:53:14   作者:niulx111  
这篇文章主要介绍了Java中的CountDownLatch使用解析,CountDownLatch初始化的时候必须指定一个count,await方法会一直阻塞直到调用countdown方法,count为0,当count为0时,所有的等待线程都会被释放,需要的朋友可以参考下

CountDownLatch同步工具类

CountDownLatch初始化的时候必须指定一个count,await方法会一直阻塞直到调用countdown方法,count为0,当count为0时,所有的等待线程都会被释放。

count是不能被重置的,如果想重复使用count,可以考虑CyclicBarrier。

CountDownLatch是一个同步工具类,用来协调多个线程之间的同步,或者是线程之间的通信。

CountDownLatch可以使主线程等待子线程完成自己的任务之后在继续执行,count为线程的数量,每当线程完成一个任务后,count减一,当count为0时,表示所有的任务都已经完成,这时主线程就可以继续执行。

CountDownLatch的构造函数

    public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
    }

初始化的时候必须指定一个大于等于0的count,否则会抛出异常。

        Sync(int count) {
            setState(count);
        }

CountDownLatch的同步是使用了AQS的状态代表count。

看一下它的countdown方法。

    /**
     * 如果count为0时,释放所有的等待线程
     * 如果当前的count比0大就要递减
     * 如果当前count为0什么也不做
     */
    public void countDown() {
        sync.releaseShared(1);
    }

本质还是调用了AQS的releaseShared方法。

    public final boolean releaseShared(int arg) {
        if (tryReleaseShared(arg)) {
            doReleaseShared();
            return true;
        }
        return false;
    }
protected boolean tryReleaseShared(int releases) {
            // Decrement count; signal when transition to zero
            for (;;) {
                int c = getState();
                if (c == 0)
                    return false;
                int nextc = c-1;
                if (compareAndSetState(c, nextc))
                    return nextc == 0;
            }
        }

countdown就是释放锁的操作,每被调用一次,state就减一。首先尝试释放锁,利用CAS设置state,如果state为0,说明所有的子线程都完成了操作,这是就要唤醒在同步队列上的其他线程。

再来看一下await方法。

    public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }
    public final void acquireSharedInterruptibly(int arg)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        if (tryAcquireShared(arg) < 0)
            doAcquireSharedInterruptibly(arg);
    }
        protected int tryAcquireShared(int acquires) {
            return (getState() == 0) ? 1 : -1;
        }

尝试获取锁,如果state为0,表示获取锁成功,如果state不为0,表示获取锁失败,调用doAcquireSharedInterruptibly方法阻塞直到成功获取到锁。

CountDownLatch的使用

public static void main(String[] args) throws Exception {
		java.util.concurrent.CountDownLatch c = new java.util.concurrent.CountDownLatch(3);
		ExecutorService es = Executors.newCachedThreadPool();
		for (int i = 0; i < 3; i++) {
			es.execute(new Task(i, c));
		}
		c.await();
		System.out.println("主线程执行任务");
	}
	public static class Task implements Runnable {
		private int m;
		private java.util.concurrent.CountDownLatch c;
		public Task(int m,java.util.concurrent.CountDownLatch c) {
			this.m = m;
			this.c = c;
		}
		@Override
		public void run() {
			System.out.println("子线程"+m+"完成了任务");
			c.countDown();
		}
	}

执行结果

子线程1完成了任务
子线程0完成了任务
子线程2完成了任务
主线程执行任务

在多线程中,子线程需要完成各自的任务后,主线程才能利用子线程的结果进行整合,我们可以考虑CountDownLatch来控制并发。

CountDownLatch只是一个同步辅助类,当CountDownLatch的计数器未到0之前,所有调用await的方法都会阻塞,只有计数器为0,线程才能继续往下执行。CountDownLatch的计数器是不可重用的。

到此这篇关于Java中的CountDownLatch同步工具类使用解析的文章就介绍到这了,更多相关CountDownLatch同步工具类解析内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 基于Java实现简易的局域网对话系统

    基于Java实现简易的局域网对话系统

    这篇文章主要介绍了基于Java实现的简易的局域网对话系统,文中的示例代码对我们学习Java有一定的帮助,感兴趣的小伙伴快来跟随小编一起学习一下吧
    2021-12-12
  • List、Map、Set接口在Java中的存取元素特点详细探讨

    List、Map、Set接口在Java中的存取元素特点详细探讨

    在Java编程语言中集合框架是处理对象组的重要工具,主要包括List、Set和Map接口,这些接口及其实现类提供了丰富的功能,这篇文章主要给大家介绍了关于List、Map、Set接口在Java中的存取元素特点,需要的朋友可以参考下
    2024-08-08
  • java接口防重提交的处理方法

    java接口防重提交的处理方法

    本文主要介绍了java接口防重提交的处理方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05
  • Java 实现模拟用户登录的示例代码

    Java 实现模拟用户登录的示例代码

    这篇文章主要介绍了Java 实现模拟用户登录的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • Springboot工具类FileCopyUtils使用教程

    Springboot工具类FileCopyUtils使用教程

    这篇文章主要介绍了Springboot内置的工具类之FileCopyUtils的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2022-12-12
  • log4j2动态修改日志级别及拓展性使用详解

    log4j2动态修改日志级别及拓展性使用详解

    这篇文章主要介绍了log4j2动态修改日志级别及拓展性使用详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-11-11
  • 基于jstree使用JSON数据组装成树

    基于jstree使用JSON数据组装成树

    这篇文章主要为大家详细介绍了基于jstree使用JSON数据组装成树,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08
  • Springboot项目的Mapper中增加一个新的sql语句

    Springboot项目的Mapper中增加一个新的sql语句

    本文主要介绍了Springboot项目的Mapper中增加一个新的sql语句,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-05-05
  • JavaWeb如何实现限制单个账号多处登录

    JavaWeb如何实现限制单个账号多处登录

    这篇文章主要介绍了JavaWeb如何实现限制单个账号多处登录问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • javafx实现图片3D翻转效果方法实例

    javafx实现图片3D翻转效果方法实例

    程序实现思路: 在javafx中Node对象有一个effect属性,可以用于实现各种特效。PerspectiveTransform特效可以使Node对象实现透视变换。因此我们可以通过计算透视变换中每个点的位置来实现3D翻转特效。
    2013-04-04

最新评论