J.U.C 系列之 Tools
JDK 5.0 开始,java并发大师Doug lea 为我们带来了更高效更应用的java并发API Java.util.concurrent包,简称J.U.C
J.U.C 体系由如下五个知识结构构成
本节我们首先来介绍其中的并发辅助工具类 Tools
Tools又由几个主要的工具类构成,如下所示‘
一 等待多线程完成的CountDownLatch
CountDownLatch允许一个或者多个线程等待其他线程完成操作。
假如有这样一个需求:我们需要解析一个Excel表里面的多个sheet数据,此时可以考虑使用多线程,每个线程解析一个sheet里的数据,等到多有sheet的数据都解析完成之后,程序需要提示解析完成。在这个需求里面要求实现主线程等待所有线程完成sheet的解析操作,最简单的就是使用Thread 的join方法,这里不在讨论,若不清楚可以自行查看,我们这里来看看若使用CountDownLatch如何实现。
代码如下若是
import java.util.concurrent.CountDownLatch;
public class CountDownLatchTest {
/*
* CountDownLatch 构造函数接受一个int 类型的参数作为计数器。如果你想等待N个点完成,
这里就传入N.这里我们测试等待2个点完成
每次调用countDown方法N就会减一
*/
static CountDownLatch c = new CountDownLatch(2);
public static void main(String[] args) throws InterruptedException {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(1);
c.countDown();
System.out.println(2);
c.countDown();
}
}).start();
//await 方法会阻塞当前线程,直到计数器N的值变为0,
//由于countDown方法可以在任何线程执行,所以这里的N个点可以是N个线程
c.await();
System.out.println(3);
}
}
如果某个sheet的解析处理的异常缓慢,我们不可能让主线程一直等待,所以可以使用另一个带超时等待的await方法await(Long time,TimeUnit unit),这个方法等待指定时间后,就不会继续阻塞当前线程。
注:countDownLatch不能够重新初始化或者修改内部计数器值
二 同步循环屏障 CyclicBarrier
CyclicBarrier的字面量的意思是可循环使用的屏障。它主要做的是,让一组线程达到一个屏障时被阻塞,直到最后一个线程到达屏障点时,屏障才会被打开,所有被屏障拦截的线程才会继续执行。
具体效果图如下所示
CyclicBarrier 提供2个构造方法:
public CyclicBarrier(int parties, Runnable barrierAction) {
}
public CyclicBarrier(int parties) {
}
参数parties指让多少个线程或者任务等待至barrier状态;参数barrierAction为当这些线程都达到barrier状态时首先执行的任务。
下面我们通过实例演示如何使用CyclicBarrier
package com.wirt; import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier; public class CyclicBarrierTest { static CyclicBarrier c = new CyclicBarrier(2,new A()); public static void main(String[] args) throws InterruptedException {
new Thread(new Runnable() {
@Override
public void run() {
try {
c.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println(1); }
}).start(); try {
c.await();
} catch (BrokenBarrierException e) {
e.printStackTrace();
} System.out.println(2);
} static class A implements Runnable{ @Override
public void run() {
System.out.println(3);
} }
}
因为设置了拦截数量是2,且两个线程都到达屏障后优先执行A任务,然后在执行到达屏障的任务
三 控制并发线程数的Semaphore
Semaphore(信号量)是用来控制同时访问特定资源的线程数量,他通过协调各个线程以保证合理的使用公共资源。
Semaphore 可以用于做流量控制,特别是公共资源的应用场景,比如数据库连接,加入有一个需求,要读取几万个文件的数据,因为都是IO密集型任务,我们可以启动几十个线程并发的读取。但是到读到内存后,还是要存储到数据库中,而数据库的连接数只有十个,这是我们必须控制只有十个线程同时获取数据库连接保存数据,否则报错无法获取数据库连接,这个时候,就可以使用Semaphore来做流量控制。示例代码如下
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore; public class SemaphoreTest { private static final int COUNT = 30; private static ExecutorService threadPool = Executors.newFixedThreadPool(COUNT); private static Semaphore s = new Semaphore(10); public static void main(String[] args) {
for(int i =0;i<COUNT;i++){
threadPool.execute(new Runnable() { @Override
public void run() {
try {
s.acquire(); //获取许可证
System.out.println("save data");
s.release(); //释放许可证
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
} threadPool.shutdown();
}
}
在代码中,虽然有30个线程任务在执行,但是只有10个线程可以同时并发执行。
四 线程间交换数据的Exchanger
Exchanger 是一个用于线程间协作的工具类,用于进行线程间的数据交换,它提供一个同步点,在这个同步点,两个线程通过执行exchanger方法,进行交换数据,如果第一个线程先执行exchanger,它会阻塞等待第二个线程执行exchanger方法,当两个线程都达到同步点时,这两个线程交换数据。
下面通过示例演示Exchanger用法
package com.wirt; import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore; public class ExchangerTest {
private static final Exchanger<String> exgr = new Exchanger<String>(); private static final ExecutorService threadPool = Executors.newFixedThreadPool(2); public static void main(String[] args) {
threadPool.execute(new Runnable() { @Override
public void run() {
String A = "银行流水A"; //A录入银行流水数据
try {
exgr.exchange(A);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}); threadPool.execute(new Runnable() { @Override
public void run() {
String B = "银行流水B"; //B录入银行流水数据
try {
String A = exgr.exchange(B);
System.out.println("A和B数据是否一致:"+A.equals(B)+"; A="+A+"; B="+B);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}); threadPool.shutdown();
}
}
五 总结
| 工具类 | 使用场景 |
| CountDownLatch | 多线程同时解析一个Excel中多个sheet,等到所有sheet解析完成,程序提示完成 |
| CyclicBarrier | 多线程计算数据,最后合并计算结果 |
| Semaphore | 用于流量控制,特别是公共资源有限情况下的应用场景,例如数据库连接 |
| Exchanger | 1 可以用于遗传算法 2 可以用于校对工作 |
参考:《Java并发编程艺术》
工具类之Executors放在下一节
J.U.C 系列之 Tools的更多相关文章
- J.U.C 系列 Tools之Executors
上个章节说了Tools中的其他四个工具类,本节我们来看一看工具类中的老大Executors,为什么说它是老大,肯定是因为他的功能最多最强大. 一 Executors是什么 Executors 是一个线 ...
- j.u.c系列(11)---之并发工具类:Exchanger
写在前面 前面三篇博客分别介绍了CyclicBarrier.CountDownLatch.Semaphore,现在介绍并发工具类中的最后一个Exchange.Exchange是最简单的也是最复杂的,简 ...
- j.u.c系列(06)---之锁条件:Condition
写在前面 在没有Lock之前,我们使用synchronized来控制同步,配合Object的wait().notify()系列方法可以实现等待/通知模式.在Java SE5后,Java提供了Lock接 ...
- j.u.c系列(03)---之AQS:AQS简介
写在前面 Java的内置锁一直都是备受争议的,在JDK 1.6之前,synchronized这个重量级锁其性能一直都是较为低下,虽然在1.6后,进行大量的锁优化策略,但是与Lock相比synchron ...
- Day9 - J - 吉哥系列故事——恨7不成妻 HDU - 4507
单身! 依然单身! 吉哥依然单身! DS级码农吉哥依然单身! 所以,他生平最恨情人节,不管是214还是77,他都讨厌! 吉哥观察了214和77这两个数,发现: 2+1+4=7 7+7=7*2 77=7 ...
- j.u.c系列(10)---之并发工具类:Semaphore
写在前面 Semaphore是一个计数信号量,它的本质是一个"共享锁". 信号量维护了一个信号量许可集.线程可以通过调用acquire()来获取信号量的许可:当信号量中有可用的许可 ...
- j.u.c系列(09)---之并发工具类:CyclicBarrier
写在前面 CyclicBarrier是一个同步辅助类,允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point).因为该 barrier 在释放等待线程后可以重用,所以 ...
- j.u.c系列(08)---之并发工具类:CountDownLatch
写在前面 CountDownLatch所描述的是”在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待“:用给定的计数 初始化 CountDownLatch.由于调用了 countDo ...
- j.u.c系列(07)---之读写锁:ReentrantReadWriteLock
写在前面 重入锁ReentrantLock是排他锁,排他锁在同一时刻仅有一个线程可以进行访问,但是在大多数场景下,大部分时间都是提供读服务,而写服务占有的时间较少.然而读服务不存在数据竞争问题,如果一 ...
随机推荐
- 一个基于 easyui, vue 和 maptalks 的简单地图应用
一个基于 easyui, vue 和 maptalks 的简单地图应用 做了一个小应用,结合 easyui , vue 和 maptalks 的简单的地图应用.可以用来画图,什么的. 地址
- CI框架更新与删除
$this->load->database(); // $query=$this->db->get('t_repayments'); // $res ...
- asp.net 在IIS上配置出现的一些问题
1.可能会遇到一下图的错无.请求的内容似乎是脚本.因而将无法由静态文件处理程序来处理---大概的原因是应用程序池选择错误了.如第二幅图如此解决即可 解决方案如下两个图所示. 我遇到了以上的问题之后能也 ...
- Xcode8-beat升级需谨慎
Xcode8-beat版本在打开xib文件的时候,出现了如下的弹窗 在这里要选择Cancel,选择Choose后xib文件的verson会改变,那么Xcode7就没法打开了(坑队友啦), 更没法运行 ...
- SID1190471 / 烦人的幻灯片 暴力出奇迹 !!!!!!!!!!!!!!!!!!
PID221 / 烦人的幻灯片 ☆ 提交你的代码 查看讨论和题解 你还木有做过哦 我的状态 查看最后一次评测记录 质量还不能统计出来哦~ 题目评价 质量 无 ★★★★★ ★★★★☆ ★ ...
- 解决IE8的兼容问题
本文分享下我在项目中积累的IE8+兼容性问题的解决方法.根据我的实践经验,如果你在写HTML/CSS时候是按照W3C推荐的方式写的,然后下面的几点都关注过,那么基本上很大一部分IE8+兼容性问题都OK ...
- oracle 清空数据库缓存
oracle 清除数据库缓存: alter system flush shared_pool ; alter system flush BUFFER_CACHE ;
- isset或array_key_exists,检查数组键是否存在
今天在导出报表的时候遇到了一个问题,undefined index:pid,然后就纳闷了,我的数组里面根本就没有pid,为什么会出现这个错误呢,我遍历了一下数组,发现果然有pid这个键,奇怪呀,我有做 ...
- Entity Framework --Entity SQL注意事项
Entity SQL 是 ADO.NET 实体框架 提供的 SQL 类语言,用于支持 实体数据模型 (EDM).Entity SQL 可用于对象查询和使用 EntityClient 提供程序执行的查询 ...
- HTML和CSS中一些有趣的
CSS Rese http://yui.yahooapis.com/3.18.1/build/cssreset/cssreset-min.css <link rel="styleshe ...