CountDownLatch 的使用场景:在主线程中开启多线程去并行执行任务,并且主线程需要等待所有子线程执行完毕后汇总返回结果。

我把源码中的英文注释全部删除,写上自己的注释。就剩下 70 行不到的代码,很简单了。

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer; public class CountDownLatch {
// 自定义一个属性,继承 抽象队列同步器
private static final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 4982264981922014374L; Sync(int count) {
setState(count);
} int getCount() {
return getState();
} @Override
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
} @Override
protected boolean tryReleaseShared(int releases) {
for (;;) {
int c = getState();
if (c == 0) {
return false;
}
int nextc = c-1;
if (compareAndSetState(c, nextc)) {
return nextc == 0;
}
}
}
}
//定义私有属性,该类继承 抽象队列同步器
private final java.util.concurrent.CountDownLatch.Sync sync; // 构造方法,传入数字,用于倒计数
public CountDownLatch(int count) {
if (count < 0) {
throw new IllegalArgumentException("count < 0");
}
this.sync = new java.util.concurrent.CountDownLatch.Sync(count);
}
// 阻塞当前线程,直到count=0才唤醒线程
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
// 阻塞当前线程,直到count=0才唤醒线程。
// 设置定时时间到了,也会唤醒线程。
public boolean await(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
//count 减 1
public void countDown() {
sync.releaseShared(1);
}
//获取 count
public long getCount() {
return sync.getCount();
}
//toString方法,获取字符串
public String toString() {
return super.toString() + "[Count = " + sync.getCount() + "]";
}
}

我用这个CountDownLatch来实现多线程执行任务,合并结果返回。

//创建线程池
ExecutorService pool = Executors.newCachedThreadPool();
//定义集合存储结果
List<Object> values = new ArrayList<>();
//定义倒计数器
CountDownLatch count = new CountDownLatch(2); //线程池执行任务1
pool.submit(new Runnable() {
@Override
public void run() {
try {
//线程池进行计算1,得到结果1。
String value1 = "结果1";
//把结果加入共享变量中。
values.add(value1);
} catch (Exception e) {
e.printStackTrace();
}finally {
//finally 中保证一定会执行 减1
//计数器减 1
count.countDown();
} }
}); //线程池执行任务2
pool.submit(new Runnable() {
@Override
public void run() {
try {
//线程池进行计算2,得到结果2。
String value2 = "结果2";
//把结果加入共享变量中。
values.add(value2);
} catch (Exception e) {
e.printStackTrace();
}finally {
//finally 中保证一定会执行 减1
//计数器减 1
count.countDown();
} }
});
//线程阻塞等待
count.await(); //返回多线程执行的结果。
return values;

  多线程并发编程,就是这么简单!不用Callable,也能获取到线程池的返回值哦。

JAVA并发编程之倒计数器CountDownLatch的更多相关文章

  1. Java并发编程-JUC-CountDownLatch 倒计数门闩器-等待多线程完成再放行 -一次性使用

    如题 (总结要点) CountDownLatch 倒计数门闩器, 让1-n-1个线程等待其他多线程完成工作. (Excel的多个Sheet的解析,最终等待解析完毕后;要实现主线程等待所有线程完成she ...

  2. 并发编程-concurrent指南-计数器CountDownLatch

    java.util.concurrent.CountDownLatch 是一个并发构造,它允许一个或多个线程等待一系列指定操作的完成. CountDownLatch 以一个给定的数量初始化.count ...

  3. Java并发编程:Semaphore、CountDownLatch、CyclicBarrier

    首先我们来实现一个功能:当我们启动一个系统的时候需要初始化许多数据,这时候我们可能需要启动很多线程来进行数据的初始化,只有这些系统初始化结束之后才能够启动系统.其实在Java的类库中已经提供了Sema ...

  4. Java并发编程_wait/notify和CountDownLatch的比较(三)

     1.wait/notify方法 package sync; import java.util.ArrayList; import java.util.List; public class WaitA ...

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

    上篇博文([Java并发编程实战]-----"J.U.C":CyclicBarrier)LZ介绍了CyclicBarrier.CyclicBarrier所描述的是"允许一 ...

  6. Java并发编程:CountDownLatch、CyclicBarrier和Semaphore

    Java并发编程:CountDownLatch.CyclicBarrier和Semaphore 在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch ...

  7. Java并发编程的4个同步辅助类(CountDownLatch、CyclicBarrier、Semaphore、Phaser)

    我在<JDK1.5引入的concurrent包>中,曾经介绍过CountDownLatch.CyclicBarrier两个类,还给出了CountDownLatch的演示案例.这里再系统总结 ...

  8. Java并发编程的4个同步辅助类(CountDownLatch、CyclicBarrier、Semphore、Phaser)

    我在<jdk1.5引入的concurrent包>中,曾经介绍过CountDownLatch.CyclicBarrier两个类,还给出了CountDownLatch的演示案例.这里再系统总结 ...

  9. 14、Java并发编程:CountDownLatch、CyclicBarrier和Semaphore

    Java并发编程:CountDownLatch.CyclicBarrier和Semaphore 在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch ...

随机推荐

  1. 对比Hashtable,HashMap,TreeMap,谈谈对HashMap的理解

    都实现了Map接口,存储的内容是基于key-value的键值对映射,一个映射不能有重复的键,一个键最多只能映射一个值. 1.初始化的时候:HashTable在不指定容量的情况下的默认容量是11,且不要 ...

  2. PHP 碎碎念

    class Object { public static function get_self() { return new self(); } public static function get_s ...

  3. Android 蓝牙开发(2)——低功耗蓝牙

    低功耗蓝牙官方文档 本文章是参考官网,然后加入自己实践中的理解完成!没有看上一篇的读者,可以先阅读一下前一篇,这是一个系列. 官网地址:https://developer.android.com/gu ...

  4. Jrebel激活服务搭建

    前言 因为平时的开发工具是使用IntelliJ IDEA,所以热部署项目代码的时候,使用的Jrebel.因为Jrebel是收费的,所以以前用的时候都是在网上找破解方法(国人通用做法),在网上找到的办法 ...

  5. python - 博客目录

    博客目录 python基础部分 函数 初识函数 函数进阶 装饰器函数 迭代器和生成器 内置函数和匿名函数 递归函数 常用模块 常用模块 模块和包 面向对象 初识面向对象 面向对象进阶 网络编程 网络编 ...

  6. 从同步原语看非阻塞同步以及Java中的应用

    非阻塞同步:基于冲突检测的乐观并发策略,通俗讲就是先进行操作,如果没有其他线程争用共享数据,那操作就成功了,如果争用数据有冲突那就采用其他的补偿措施(最常见的就是不断重试直到成功),这种乐观的并发策略 ...

  7. Codeforces Gym101341K:Competitions(DP)

    http://codeforces.com/gym/101341/problem/K 题意:给出n个区间,每个区间有一个l, r, w,代表区间左端点右端点和区间的权值,现在可以选取一些区间,要求选择 ...

  8. 1. UML软件设计模型图整理

    UML建模 程序设计ER图 UML建模(一)---UserCase用例图 UML建模(二)--流程图 (程序框图) UML建模(三)--部署图 UML建模(四)--类图 UML用例图.流程图 (五)

  9. 19.linux文件属性

    1.linux文件属性 ls -lih i查看文件inode,h查看文件大小 文件总共10个属性 inode索引节点编号(唯一的) 文件类型和权限,第一个字符为类型,后面字符为权限 硬链接的数量 文件 ...

  10. MyBatis从入门到精通:insert用法

    2.4.1 简单的insert方法 1.接口类中的方法: int insert(SysUser sysUser); 2.映射文件中的修改: <!-- insert标签包含如下的属性: id: p ...