Java核心复习 —— J.U.C 并发工具类
一、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 并发工具类的更多相关文章
- Java核心复习——J.U.C AbstractQueuedSynchronizer
第一眼看到AbstractQueuedSynchronizer,通常都会有这几个问题. AbstractQueuedSynchronizer为什么要搞这么一个类? 这个类是干什么的.有什么用? 这个类 ...
- Java核心复习——J.U.C LinkedBlockingQueue源码分析
参考文档 LinkedBlockingQueue和ArrayBlockingQueue的异同
- Java核心复习——J.U.C ArrayBlockingQueue源码分析
介绍 依赖关系 源码 构造方法 public ArrayBlockingQueue(int capacity) { this(capacity, false);//默认构造非公平的有界队列 } pub ...
- Java并发指南9:AQS共享模式与并发工具类的实现
一行一行源码分析清楚 AbstractQueuedSynchronizer (三) 转自:https://javadoop.com/post/AbstractQueuedSynchronizer-3 ...
- Java并发编程-并发工具类及线程池
JUC中提供了几个比较常用的并发工具类,比如CountDownLatch.CyclicBarrier.Semaphore. CountDownLatch: countdownlatch是一个同步工具类 ...
- Java并发(十六):并发工具类——Exchanger
Exchanger(交换者)是一个用于线程间协作的工具类.Exchanger用于进行线程间的数据交换.它提供一个同步点,在这个同步点两个线程可以交换彼此的数据.这两个线程通过exchange方法交换数 ...
- Java并发(十五):并发工具类——信号量Semaphore
先做总结: 1.Semaphore是什么? Semaphore(信号量)是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源. 把它比作是控制流量的红绿灯,比如XX马路要 ...
- Java并发(十四):并发工具类——CountDownLatch
先做总结: 1.CountDownLatch 是什么? CountDownLatch 允许一个或多个线程等待其他线程(不一定是线程,某个操作)完成之后再执行. CountDownLatch的构造函数接 ...
- Java并发(十三):并发工具类——同步屏障CyclicBarrier
先做总结 1.CyclicBarrier 是什么? CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier).它要做的事情是,让一组线程到达一个屏障(也可以叫同步点) ...
随机推荐
- web前端如何优化自己的代码
前端的性能优化主要分为三部分: HTML优化 避免 HTML 中书写 CSS 代码,因为这样难以维护. 使用Viewport加速页面的渲染. 使用语义化标签,减少 CSS 代码,增加可读性和 SEO. ...
- SMARTY的知识
smarty的原理: <?php class Smarty { $ldelimiter = "{";//左分隔符 $rdelimiter = "}";// ...
- Qt布局
常用的布局方法 1. 水平布局类 QHBoxLayout 2. 垂直布局类 QVBoxLayout 3. 网格布局类 QGridLayout QHBoxLayout 对象横向排列开 QVBoxLayo ...
- fatfs源码阅读
使用fatfs文件的第一步,就是调用F_mount函数注册一个工作空间. F_mount函数的原型如下: 第一个参数根据网上大神的答复,是外设类型,如果是sd卡就是0,flash等等其他的外设就是其他 ...
- Feign报错'xx.FeignClientSpecification', defined in null, could not be registered.
解决: 在application.yml中配置: spring: main: allow-bean-definition-overriding: true 参考:https://blog.csdn.n ...
- Nginx 之 Rewrite 规则
write 规则介绍 Rewite 规则作用 Rewrite规则可以实现对url的重写,以及重定向 作用场景: URL访问跳转,支持开发设计,如页面跳转,兼容性支持,展示效果等 SEO优化 维护:后台 ...
- mysql存储过程事务
之前在写一个存储过程的时候由于不仔细导致数据库锁死,这里反省一下. 存储过程是这样的:把数据按顺序插入三张表,如果其中任何一处出错,就把前面已经做了的操作进行回滚,存储过程里面是用事务实现的,我是这么 ...
- linux 安装mysql(rpm文件安装)
三 卸载旧版本的MySql (没有的话,则跳过此步骤) 1.查看旧版本MySql rpm -qa | grep mysql 将会列出旧版本MySql的组件列表,如: ...
- Java锁--Semaphore
转载请注明出处:http://www.cnblogs.com/skywang12345/p/3534050.html Semaphore简介 Semaphore是一个计数信号量,它的本质是一个&quo ...
- Django中的Session与Cookie
1.相同与不同 Cookie和Session都是为了记录用户相关信息的方式, 最大的区别就是Cookie在客户端记录而Session在服务端记录内容. 2.Cookie和Session之间的联系的建立 ...