一、CountDownLatch

文档描述

A synchronization aid that allows one or more threads to wait until* a set of operations being performed in other threads completes.

是一个同步帮助工具,允许一个或多个线程等待一系列其他线程操作完后,再执行。

count down 倒计时

latch 插锁

在Java中Latch结尾的也叫 闭锁

用法

方法名 作用
await() 线程会被挂起,它会等待直到count值为0才继续执行

简单示例


public class CountDownLatchDemo { private static final ExecutorService threadPool = new ThreadPoolExecutor(50, 100,
5, TimeUnit.SECONDS,
new SynchronousQueue<>(),
new BasicThreadFactory.Builder().namingPattern("thread-%d").build()); public static void main(String[] args) throws InterruptedException { CountDownLatch countDownLatch = new CountDownLatch(10);
for (int i = 1; i <= 10; i++) {
threadPool.execute(() -> {
System.out.println("test-"+new Random().nextInt());
countDownLatch.countDown();
});
} countDownLatch.await();
System.out.println("end");
threadPool.shutdown(); } }

应用场景

同事A需要执行任务A,进行A类数据的收集

同事B需要执行任务B,进行B类数据的收集

项目经理需要等到A和B的数据都收集齐之后,进行统计,然后向上汇报。

public class CountDownLatchDemo2 {

    private static final ExecutorService threadPool = new ThreadPoolExecutor(50, 100,
5, TimeUnit.SECONDS,
new SynchronousQueue<>(),
new BasicThreadFactory.Builder().namingPattern("thread-%d").build()); public static void main(String[] args) { CountDownLatch countDownLatch = new CountDownLatch(2);
// 收集数据A
threadPool.execute(new TaskA(countDownLatch));
// 收集数据B
threadPool.execute(new TaskB(countDownLatch));
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 进行统计工作
System.out.println("进行统计工作");
// 向上汇报
System.out.println("向上汇报");
System.out.println("任务结束");
threadPool.shutdown();
} static class TaskA implements Runnable { private CountDownLatch countDownLatch; public TaskA(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
} @Override
public void run() { try {
System.out.println("执行任务A-----------");
TimeUnit.SECONDS.sleep(5);
System.out.println("执行任务A完成");
countDownLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} static class TaskB implements Runnable { private CountDownLatch countDownLatch; public TaskB(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
} @Override
public void run() { try {
System.out.println("执行任务B-----------");
TimeUnit.SECONDS.sleep(7);
System.out.println("执行任务B完成");
countDownLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} }

运行结果

二、Semaphore

文档描述

A counting semaphore.  Conceptually, a semaphore maintains a set of* permits.  Each {@link #acquire} blocks if necessary until a permit is* available, and then takes it.  Each {@link #release} adds a permit,* potentially releasing a blocking acquirer.* However, no actual permit objects are used; the {@code Semaphore} just* keeps a count of the number available and acts accordingly.**

Semaphores are often used to restrict the number of threads than can* access some (physical or logical) resource. For example, here is* a class that uses a semaphore to control access to a pool of items:

用于控制并发量。

用法

方法名 作用
acquire() 从该信号量获取一个许可,在获取许可前线程将一直阻塞
release() 释放一个许可,将其返回给信号量

简单示例


public class SemaphoreDemo { private static final ExecutorService threadPool = new ThreadPoolExecutor(20, 100,
1, TimeUnit.MINUTES,
new SynchronousQueue<>(),
new BasicThreadFactory.Builder().namingPattern("thread-%d").build()); private static volatile int count = 0; public static void main(String[] args) { Semaphore semaphore = new Semaphore(3); for (int i = 0; i < 100; i++) {
threadPool.execute(() -> {
try {
semaphore.acquire();
System.out.println("test--" + count);
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
count++;
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
} });
} } }

应用场景

公司有100个人需要体检,医院每次最多只能体检3人。

当有3个人在体检时,其他人只能等待,有1个人体检完,下一个人可以补上。

public class SemaphoreDemo {

    private static final ExecutorService threadPool = new ThreadPoolExecutor(20, 100,
1, TimeUnit.MINUTES,
new SynchronousQueue<>(),
new BasicThreadFactory.Builder().namingPattern("thread-%d").build()); private static volatile int count = 0; public static void main(String[] args) { Semaphore semaphore = new Semaphore(3); for (int i = 0; i < 100; i++) {
threadPool.execute(() -> {
try { String id = new Random().nextInt() + "";
semaphore.acquire();
System.out.println("同事ID:" + id + ",开始体检");
try {
TimeUnit.SECONDS.sleep(3L);
TimeUnit.MILLISECONDS.sleep(new Random(10000).nextInt());
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("同事ID:" + id + ",体检结束" + count);
count++;
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
} });
} } }

运行结果

三、CyclicBarrier

概念

和闭锁不同的是,栅栏是用来等待线程的,闭锁是用来等待时间。

当指定线程数都到达某个点,才开始执行后续的操作。

就好比有10个人赛跑,要跑400米,在100米设置一个栅栏,当这10个人都到达了这个栅栏的时候,才取消栅栏,全部放行。

简单示例

public class CyclicBarrierDemo {

    private static final ExecutorService threadPool = new ThreadPoolExecutor(50, 100,
1, TimeUnit.MINUTES,
new SynchronousQueue<>(),
new BasicThreadFactory.Builder().namingPattern("thread-%d").build()); public static void main(String[] args) { CyclicBarrier cyclicBarrier = new CyclicBarrier(10);
for (int i = 0; i < 10; i++) {
threadPool.execute(() -> {
System.out.println("线程" + Thread.currentThread().getId() + "跑到100米,遇到栅栏,停下");
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println("继续跑完剩下300米");
});
} threadPool.shutdown(); } }

应用场景

还用上面CountDownLatch的例子,

同事A需要执行任务A,进行A类数据的收集

同事B需要执行任务B,进行B类数据的收集

项目经理需要等到A和B的数据都收集齐之后,进行统计,然后向上汇报。


public class CyclicBarrierDemo2 { private static final ExecutorService threadPool = new ThreadPoolExecutor(50, 100,
5, TimeUnit.SECONDS,
new SynchronousQueue<>(),
new BasicThreadFactory.Builder().namingPattern("thread-%d").build()); private static volatile boolean flag = false; public static void main(String[] args) { CyclicBarrier cb = new CyclicBarrier(2);
// 收集数据A
threadPool.execute(new TaskA(cb));
// 收集数据B
threadPool.execute(new TaskB(cb));
threadPool.shutdown();
} static class TaskA implements Runnable { private CyclicBarrier cb; public TaskA(CyclicBarrier cb) {
this.cb = cb;
} @Override
public void run() { try {
System.out.println("执行任务A-----------");
TimeUnit.SECONDS.sleep(5);
System.out.println("执行任务A完成");
cb.await();
if(!flag){
flag = true;
System.out.println("进行统计工作");
System.out.println("向上汇报");
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
} static class TaskB implements Runnable { private CyclicBarrier cb; public TaskB(CyclicBarrier cb) {
this.cb = cb;
} @Override
public void run() { try {
System.out.println("执行任务B-----------");
TimeUnit.SECONDS.sleep(7);
System.out.println("执行任务B完成");
cb.await();
if(!flag){
flag = true;
System.out.println("进行统计工作");
System.out.println("向上汇报");
System.out.println("任务结束");
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
} }

运行结果

Java核心复习 —— J.U.C 并发工具类的更多相关文章

  1. Java核心复习——J.U.C AbstractQueuedSynchronizer

    第一眼看到AbstractQueuedSynchronizer,通常都会有这几个问题. AbstractQueuedSynchronizer为什么要搞这么一个类? 这个类是干什么的.有什么用? 这个类 ...

  2. Java核心复习——J.U.C LinkedBlockingQueue源码分析

    参考文档 LinkedBlockingQueue和ArrayBlockingQueue的异同

  3. Java核心复习——J.U.C ArrayBlockingQueue源码分析

    介绍 依赖关系 源码 构造方法 public ArrayBlockingQueue(int capacity) { this(capacity, false);//默认构造非公平的有界队列 } pub ...

  4. Java并发指南9:AQS共享模式与并发工具类的实现

    一行一行源码分析清楚 AbstractQueuedSynchronizer (三) 转自:https://javadoop.com/post/AbstractQueuedSynchronizer-3 ...

  5. Java并发编程-并发工具类及线程池

    JUC中提供了几个比较常用的并发工具类,比如CountDownLatch.CyclicBarrier.Semaphore. CountDownLatch: countdownlatch是一个同步工具类 ...

  6. Java并发(十六):并发工具类——Exchanger

    Exchanger(交换者)是一个用于线程间协作的工具类.Exchanger用于进行线程间的数据交换.它提供一个同步点,在这个同步点两个线程可以交换彼此的数据.这两个线程通过exchange方法交换数 ...

  7. Java并发(十五):并发工具类——信号量Semaphore

    先做总结: 1.Semaphore是什么? Semaphore(信号量)是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源. 把它比作是控制流量的红绿灯,比如XX马路要 ...

  8. Java并发(十四):并发工具类——CountDownLatch

    先做总结: 1.CountDownLatch 是什么? CountDownLatch 允许一个或多个线程等待其他线程(不一定是线程,某个操作)完成之后再执行. CountDownLatch的构造函数接 ...

  9. Java并发(十三):并发工具类——同步屏障CyclicBarrier

    先做总结 1.CyclicBarrier 是什么? CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier).它要做的事情是,让一组线程到达一个屏障(也可以叫同步点) ...

随机推荐

  1. sql server统计总成绩和排名

    这里的图片可以拖拽到一个新页面查看原图!!!! 这里有两个表,需要查询总成绩和排名 Sql语句: select ST.name,SE.Chinese,SE.Math,SE.English, ( SE. ...

  2. 1.JUC锁的一些概念

    原文链接:http://blog.csdn.net/zteny/article/details/54859228 接下来的几篇文章都转自这里,冒犯之处,多多包涵 原子性: 在看原子性之前,我们先看看什 ...

  3. RestFramework之解析器

    一.什么是解析器? 对请求的数据进行解析 - 请求体进行解析. 解析器在你不拿请求体数据时 不会调用. 安装与使用: https://www.django-rest-framework.org/ 官方 ...

  4. python之反射机制与callattr()、issubclass()、isinstance、type()相关

    一.反射机制 * 反射可以理解为 通过字符串的形式,动态导入模块: 利用字符串的形式,在对象(模块)中操作(查找/获取/删除/添加)成员,是一种基于字符串的事件驱动! 反射机制的内置函数 # hasa ...

  5. Python基础——运行机理

    Python解释器 从Python这门编程语言的实现上来讲,Python是一个名为解释器的软件包,包含:一个解释器 和 支持的库 解释器又有不同版本:CPython.Jython.IronPython ...

  6. Python 使用 docopt 解析json参数文件

    1. 背景 在深度学习的任务中,通常需要比较复杂的参数以及输入输出配置,比如需要不同的训练data,不同的模型,写入不同的log文件,输出到不同的文件夹以免混淆输出 常用的parser.add()方法 ...

  7. 基于Java+Selenium的WebUI自动化测试框架(六)---浏览器初始化

    本篇我们来讨论,如何写一个浏览器初始化的类.在写之前,先思考一下,我们需要一个什么样的初始化? 先来看看使用原生的Java + selenium是怎么做的.(以firefox为例) System.se ...

  8. 上传文件(lrzsz)

    执行命令:yum -y install lrzsz 现在就可以正常使用rz.sz命令上传.下载数据了. 上传文件,执行命令rz,会跳出文件选择窗口,选择好文件,点击确认即可. 下载文件,执行命令sz

  9. sql index改怎么建

    https://stackoverflow.com/questions/11299217/how-can-i-optimize-this-sql-query-using-indexes ------- ...

  10. Caused by: java.lang.ClassNotFoundException: org.fusesource.jansi.WindowsAnsiOutputStream

    08:23:18,995 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate append ...