CountDownLatch & CyclicBarrier
CountDownLatch
在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。用给它的代数初始化CountDownLatch,且计数器无法被重置。当前计数到达0之前,await方法一直受阻塞。
CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器就减1,当计数器值到达0时,表示所有的线程以经完成了任务,然后再闭锁上等待的线程就可以恢复执行任务。
public void countDown() 递减锁存器的计数。若计数到达零,则释放所有等待的线程。若当前计数大于0,则将计数减少。若减少为0后,将重启所有等待的线程。若当前为0,则不发生任何操作。
public boolean await(long timeout, TimeUnit unit) throws InterruptedException 使当前线程在锁存器到技术至0之前一直等待。除非线程被中断或超出了指定的等待时间。若当前技术值为0,则此方法返回true。
public class Test{
public static void main(String args[]){
final CountDownLatch latch = new CountDownLatch(2);
new Thread(){
public void run(){
try{
System.out.println("子线程" + Thread.currentThread().getName() + "正在执行");
Thread.sleep(3000);
System.out.println("子线程" + Thread.currentThread().getName() + "执行完毕");
latch.countDown();
}catch(InterruptedException e){
e.printStackTrace();
}
};
}.start();
new Thread(){
public void run(){
try{
System.out.println("子线程" + Thread.currentThread().getName() + "正在执行");
Thread.sleep(3000);
System.out.println("子线程" + Thread.currentThread().getName() + "执行完毕");
latch.countDown();
}catch(InterruptedException e){
e.printStackTrace();
}
};
}.start();
}
try{
System.out.println("等待2个子线程执行完毕...");
latch.await();
System.out.println("2个子线程已经执行完毕");
System.out.println("继续执行主线程");
}catch(InterruptedException e){
e.printStackTrace();
}
}
CyclicBarrier
可循环使用的屏障。作用是让一组线程到达一个屏障时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活,线程进入屏障通过CyclicBarrier的await()方法
CyclicBarrier默认的构造方法是CyclicBarrier(int parties),其参数表示屏障拦截的线程数量,每个线程调用await方法告诉CyclicBarrier已经到达了屏障,然后当前线程被阻塞
CyclicBarrier的另一个构造方法是CyclicBarrier(int parites, Runnable barrierAction)用于在线程到达屏障时,优先执行barrierAction这个Runnable对象
实现原理:在CyclicBarrier内部定义了一个Lock对象,每当一个线程调用CyclicBarrier的await方法时,将剩余拦截的线程数减1,然后判断剩余拦截数是否为0,若不是,进入Lock对象的条件队列等待;若是,执行barrierAction对象的Runnable方法,然后将锁的条件队列中的所有线程放入锁等待队列,这些线程会一次获取锁,释放锁,接着从await方法返回,再从CyclicBarrier的await方法返回。
public int await() throws InterruptedException, BrokenBarrierException{
try{
return dowait(false, 0L);
}catch(TimeoutException toe){
throw new Error(toe);
}
}
private int dowait(boolean timed, long nanos) throws InterruptedException, BrokenBarrierException, TimeoutException{
final ReentrantLock lock = this.lock;
lock.lock();
try{
final Generation g = generation;
if(g.broken){
throw new BrokenBarrierException();
}
if(Thread.interrupted()){
breakBarrier();
throw new InterruptedException();
}
int index = --count;
if(index ==0){
boolean ranAction = false;
try{
final Runnable command = barrierCommand;
if(command != null){
command.run();
}
ranAction = true;
nextGenreration();
return 0;
}finally{
if(!ranAction)
breakBarrier();
}
}
for(;;){
try{
if(!timed)
trip.await();
else if(nanos > 0L)
nanos = trip.awaitNanos(nanos);
}catch(InterruptedException ie){
if(g == generation && !g.broken){
breakBarrier();
throw ie;
}else{
Thread.currentThread().interrupt();
}
}
if(g.broken)
throw new BrokenBarrierException();
if(g != generation)
return index;
if(timed && nanos <= 0L){
breakBarrier();
throw new TimeoutException();
}
}
}finally{
lock.unlock();
}
private void breakBarrier(){
generation.broken = true;
count = parties;
trip.singalAll();
}
}
public class CyclicBarrierDemo{
private CyclicBarrier cb = new CyclicBarrier(4);
private Random random = new Random();
class Task implements Runnable{
private String id;
Task(String id){
this.id = id;
}
public void run(){
try{
Thread.sleep(random.nextInt(1000));
System.out.println("Thread " + id + " will wait");
cb.await();
System.out.println("------ Thread " + id + " is over");
}catch(InterruptedException e ){
}catch(BrokenBarrierException e){
}
}
}
public static void main(String[] args){
CyclicBarrierDemo cbd = new CyclicBarrierDemo();
ExecutorService es = Executors.newCachedThreadPool();
es.submit(cbd.new TaskDemo("a"));
es.submit(cbd.new TaskDemo("b"));
es.submit(cbd.new TaskDemo("c"));
es.submit(cbd.new TaskDemo("d"));
es.shutdown();
}
}
CyclicBarrier和CountDownLatch的区别
CyclicBarrier的计数器提供reset功能,可以多次使用。但CountDownLatch只可用一次。
CountDownLatch:一个或多个线程,等待其他多个线程完成某件事情之后才能执行
CyclicBarrier:多个线程互相等待,直到到达同一个同步点,再继续一起执行
CountDownLatch & CyclicBarrier的更多相关文章
- java 并发工具类CountDownLatch & CyclicBarrier
一起在java1.5被引入的并发工具类还有CountDownLatch.CyclicBarrier.Semaphore.ConcurrentHashMap和BlockingQueue,它们都存在于ja ...
- 并发包下常见的同步工具类详解(CountDownLatch,CyclicBarrier,Semaphore)
目录 1. 前言 2. 闭锁CountDownLatch 2.1 CountDownLatch功能简介 2.2 使用CountDownLatch 2.3 CountDownLatch原理浅析 3.循环 ...
- CountDownLatch/CyclicBarrier/Semaphore 使用过吗?
CountDownLatch/CyclicBarrier/Semaphore 使用过吗?下面详细介绍用法: 一,(等待多线程完成的)CountDownLatch 背景; countDownLatch ...
- CountDownLatch CyclicBarrier和 Semaphore
CountDownLatch CyclicBarrier和 Semaphore 原理 基于AQS实现. 让需要的暂时阻塞的线程,进入一个死循环里面,得到某个条件后再退出循环,以此实现阻塞当前线程的效果 ...
- Java并发编程工具类 CountDownLatch CyclicBarrier Semaphore使用Demo
Java并发编程工具类 CountDownLatch CyclicBarrier Semaphore使用Demo CountDownLatch countDownLatch这个类使一个线程等待其他线程 ...
- 并发包下常见的同步工具类(CountDownLatch,CyclicBarrier,Semaphore)
在实际开发中,碰上CPU密集且执行时间非常耗时的任务,通常我们会选择将该任务进行分割,以多线程方式同时执行若干个子任务,等这些子任务都执行完后再将所得的结果进行合并.这正是著名的map-reduce思 ...
- CountDownLatch, CyclicBarrier and Semaphore
Reference: [1] http://shazsterblog.blogspot.co.uk/2011/12/comparison-of-countdownlatch.html CountDow ...
- Java中的4个并发工具类 CountDownLatch CyclicBarrier Semaphore Exchanger
在 java.util.concurrent 包中提供了 4 个有用的并发工具类 CountDownLatch 允许一个或多个线程等待其他线程完成操作,课题点 Thread 类的 join() 方法 ...
- 高并发第十单:J.U.C AQS(AbstractQueuedSynchronizer) 组件:CountDownLatch. CyclicBarrier .Semaphore
这里有一篇介绍AQS的文章 非常好: Java并发之AQS详解 AQS全名:AbstractQueuedSynchronizer,是并发容器J.U.C(java.lang.concurrent)下lo ...
随机推荐
- MySql从一窍不通到入门(五)Sharding:分表、分库、分片和分区
转载:用sharding技术来扩展你的数据库(一)sharding 介绍 转载:MySQL架构方案 - Scale Out & Scale Up. 转载: 数据表分区策略及实现(一) 转载:M ...
- json字符串转Map、json数组
json数组转map public static void main(String[] args){ String strArr = "[{\"0\":\"zh ...
- 通过DBMS_REDEFINITION包对表在线重定义
基础介绍 Oracle Online Redefinition可以保证在数据表进行DDL类型操作,如插入.删除数据列,分区处理的时候,还能够支持DML操作,特别是insert/update/delet ...
- servlet初认知(持续更新中)
一:前言: 一个Servlet程序其实就是一个实现了Java特殊接口的类,它由支持Servlet(具有Servlet引擎)的WEB服务器调用和启动运行.一个Servlet程序负责处理它对应的一个或者多 ...
- [LeetCode] 43. Multiply Strings ☆☆☆(字符串相乘)
转载:43. Multiply Strings 题目描述 就是两个数相乘,输出结果,只不过数字很大很大,都是用 String 存储的.也就是传说中的大数相乘. 解法一 我们就模仿我们在纸上做乘法的过程 ...
- Express 路径请求及对应的获取路径形式
req.query // GET /search?q=tobi+ferret req.query.q // => "tobi ferret" // GET /shoes?or ...
- The difference between ppp and ndis
- TNetHTTPClient 使用
unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System ...
- day35 数据库介绍和初识sql
今日内容: 1. 代码: 简易版socketsever 2.数据库(mysql)简单介绍和分类介绍 3.mysql root修改密码 4.修改字符集编码 5.初识sql语句 1.简易版socketse ...
- hybrid几种模式
native和web适合的场景 Native: 用户体验要求高 业务变动很小(如首页) 性能要求高 Web: 业务变化频繁(如广告) 性能要求低 展示性内容 hybrid App其实会有不同的分支 方 ...