同步工具类--闭锁、信号量、栅栏的总结
来源:互联网 发布:外贸数据 编辑:程序博客网 时间:2024/05/16 01:51
闭锁用于一组线程等待(阻塞)一个外部事件的发生,这个事件发生之前这些线程阻塞,等待控制线程打开闭锁,然后这些线程同时开始执行。闭锁强调的是阻塞后的同时开始;栅栏则是一组线程相互等待,直到所有线程都到达某一点时才打开栅栏,然后线程可以继续执行,也就是说控制线程先设置一个时间点,然后这些线程各自执行,执行完等待(阻塞),直到这组线程中的所有线程执行完,然后控制线程栅栏打开,这些线程同时继续执行。栅栏强调的是各自执行完后的相互等待以及继续执行。信号量根据一个计数器控制一个结果的数量,条件满足情况下才能进行增加和移除操作,否则进行操作的线程阻塞。
工具
作用
主要方法
闭锁
(CountDownLatch)
类似于门。门初始是关闭的,试图进门的线程挂起等待开门。当负责开门进程将门打开后,所有等待线程被唤醒。
门一旦打开就不能再关闭了。
CountDownLatch(int n):指定闭锁计数器
await() :挂起等待闭锁计数器为0
countDown():闭锁计数器减1
栅栏
(CyclicBarrier)
和闭锁有类似之处。闭锁是等待“开门”事件;栅栏是等待其他线程。例如有N个线程视图通过栅栏,此时先到的要等待,直到所有线程到到达后,栅栏开启,所有等待线程被唤醒通过栅栏。
CyclicBarrier(int n):需要等待的线程数量
await():挂起等待达到线程数量
信号量
(Semaphore)
和锁的作用类似。区别是锁只允许被一个线程获取,但是信号量可以设置资源数量。当没有可用资源时,才被挂起等待。
Semaphore(int n):指定初始的资源数量
acquire():试图获取资源。当没有可用资源时挂起
release():释放一个资源
场景对比:
l 闭锁场景:几个人相约去公园游玩,在家做好准备,约定在某一时刻同时出发去公园,准备工作进行的快的不能提前出门,到点出门。
l 栅栏场景:几个人相约去公园游玩,几个人去到公园门口,要等全部到达公园门口后才一起进入公园。
l 信号量场景:几个人相约去公园游玩,等大家都到公园后,发现来的太迟了,公园游客饱和,公园限制入场游客的数量。游客在门口等待,出来一人,再进入一人,只能一个一个进入。
CountDownLatch:
public class TestHarness{
public long timeTasks(int nThreads, final Runnable task) throws InterruptedException{
final CountDownLatch startGate = new CountDownLatch(1);//全部线程开始的闭锁
final CountDownLatch endGate = new CountDownLatch(nThread);//全部线程结束的闭锁
for(int i = 0 ; i < nThreads ; i++){
Thread t = new Thread(){
public void run(){
try{
startGate.await();//所有的线程都在这里等待闭锁打开
try{
task.run();//实际要调用的方法
}finally{
endGate.countDown(); //每一个线程执行完毕,调用countDown()方法,直到全部的线程(nThreads个)执行完毕,闭锁打开
}
}catch(InterruptedException e){}
}
};
t.start(); //t.start()不会立即开始执行task.run()方法,线程一开始执行startGate.await();会等待闭锁startGate打开
}
long start = System.nanoTime();//记录开始时间
startGate.countDown();//闭锁startGate初始化为1,执行一次countDown()方法,闭锁就打开了,所有的线程可以继续执行
endGate.await();//当前线程在这里等待所有的线程执行完毕
long end = System.nonaTIme();//记录结束时间
return end - start;
}
}
semaphore :
public class BoundedHashSet<T>{
private final Set<T> set;
private final Semaphore sem;
//构造方法,初始化边界
public BoundedHashSet(int bound){
this.set = Collections.synchronizedSet(new HashSet<T>());
sem = new Semaphore(bound);//初始化许可集的大小,即该有界阻塞队列的大小
}
public boolean add(T o) throws InterruptedException{
sem.acquire();//添加元素时获取一个许可,如果剩余许可为0,则说明此有界阻塞队列已满
boolean wasAdded = false; //返回值,默认为添加元素失败。
try{
wasAdded=set.add(o);//向队列中添加元素,如果成功,则返回成功
return wasAdded;
}finally{
if(!wasAdded) sem.release(); //如果添加失败,把方法一开始获取的许可释放掉
}
}
public boolean remove (Object o){
boolean wasRemoved = set.remove(o);
if(wasRemoved) sem.release();//如果删除成功,则释放一个许可
return wasRemoved;
}
}
barrier:
class Solver {
final int N;
final float[][] data;
final CyclicBarrier barrier;
class Worker implements Runnable {
int myRow;
Worker(int row) { myRow = row; }
public void run() {
while (!done()) {
processRow(myRow); //每一个线程负责处理一行数据
try {
barrier.await(); //处理完行数据之后在这个关卡等待其他线程,当所有的线程都处理完毕,才继续向下执行
} catch (InterruptedException ex) {
return;
} catch (BrokenBarrierException ex) {
return;
}
}
}
}
public Solver(float[][] matrix) {
data = matrix;
N = matrix.length;
barrier = new CyclicBarrier(N,
new Runnable() {
public void run() {
mergeRows(...); //汇总计算的结果语句
}//关卡CyclicBarrier 初始化时参数一为:关卡需要等待的线程的数量n,只有当n个线程全部到达此关卡,才能顺利通过;参数二为:一个关卡行为,当关卡顺利通过之后,在一个子任务线程中执行这个行为。Runnable类型~
});
for (int i = 0; i < N; ++i)
new Thread(new Worker(i)).start(); //每一行一个线程处理,分别启动
waitUntilDone();
}
}
- 同步工具类--闭锁、信号量、栅栏的总结
- 同步工具类--闭锁、信号量、栅栏的总结
- 同步工具类闭锁,栅栏,信号量
- 同步工具类(闭锁,信号量,栅栏,FutureTask)
- 同步工具类--闭锁
- 同步工具类-闭锁
- 同步工具类-闭锁CountDownLatch
- 闭锁/栅栏/信号量/FutureTask分析及使用
- 闭锁、栅栏、交换机、信号量学习笔记
- java并发基础(二)--- Java监视器模型、并发容器、同步工具类(闭锁、信号量)
- 闭锁、同步屏障、信号量详解
- Java同步工具类——闭锁
- JAVA栅栏和闭锁的区别
- 同步容器类和工具类4——闭锁
- 同步工具类一:闭锁(java.util.concurrent.CountDownLatch)
- 同步工具类一:闭锁(java.util.concurrent.CountDownLatch)
- java并发之同步工具类一之闭锁Latch
- Java并发编程的艺术(八)——闭锁、同步屏障、信号量详解
- android 使用shape 画虚线
- 排序
- 计算手续费
- Java学习之InputStream中read()与read(byte[] b)
- Spring IOC设计原理解析:本文乃学习整理参考而来
- 同步工具类--闭锁、信号量、栅栏的总结
- 关于利用JDBC连接sqlserver中数据库的问题
- mysql主从数据库同步和字符集问题
- Linux进程间通信——使用共享内存
- 【C/C++开发】【Java开发】JNI的替代者—使用JNA访问Java外部功能接口
- Java中断线程的方法
- map集合的使用
- Webkit样式库
- android native service编写及两个服务进程通讯