CountDownLatch, CyclicBarrier and Semaphore
Reference:
[1] http://shazsterblog.blogspot.co.uk/2011/12/comparison-of-countdownlatch.html
CountDownLatch vs CyclicBarrier
CountDownLatch can not be reused after meeting the final count.
CountDownLatch can not be used to wait for Parallel Threads to finish.
CyclicBarrier can be reset thus reused
CyclicBarrier can be used to wait for Parallel Threads to finish.
CountDownLatch
CountDownLatch can be used to monitor the completion of the Children Threads if the size of the created children is known forehand. CountDownLatch enables a Thread or Threads to wait for completion of Children Threads. But there is no waiting amongst the Children until they finish each others tasks. Children may execute asynchronously and after their work is done will exit making a countdown.
Practical Example : Main thread creates 10 Database Connections and Creates 10 different Threads and assigns those DB connection to the threads one each. But the Main thread must wait until all 10 Threads finish their DB Operation before closing the DB Connections. Children will exit after performing the DB Operation. A CountDownLatch can be used in this scenario.
import java.util.concurrent.*;
import java.util.*;
import java.text.*;
/**
* @author Shazin Sadakath
*
*/
public class CountDownLatchTest {
private static final int MAX_THREADS = 5; public static void main(String[] args) throws Exception {
CountDownLatch countDownLatch = new CountDownLatch(MAX_THREADS); System.out.println("Spawning Threads");
for(int i=0;i<MAX_THREADS;i++) {
Thread t = new Thread(new WorkerThread(countDownLatch, String.format("Thread-%d", i)));
t.start();
}
System.out.println("Spawning Finished");
System.out.println("Waiting All Threads to Finish");
countDownLatch.await(); // Await is void
System.out.println("All Threads are Finished");
} private static class WorkerThread implements Runnable {
private CountDownLatch countDownLatch; private String name; public WorkerThread(CountDownLatch countDownLatch, String name) {
this.name = name;
this.countDownLatch = countDownLatch;
} public void run() {
try {
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
System.out.printf("%s : Doing Some Work on %s\n", getFormattedDate(sdf), name);
Thread.sleep(getRandomWaitTime());
System.out.printf("%s : Doing Some more work on %s\n", getFormattedDate(sdf), name);
Thread.sleep(getRandomWaitTime());
System.out.printf("%s : Finished work on %s\n", getFormattedDate(sdf), name);
countDownLatch.countDown();
System.out.printf("%s : Count Down Latch count on %s is %d\n", getFormattedDate(sdf), name, countDownLatch.getCount());
} catch(Exception e) {
e.printStackTrace();
}
} private String getFormattedDate(SimpleDateFormat sdf) {
return sdf.format(new Date());
} private int getRandomWaitTime() {
return (int) ((Math.random() + 1) * 1000);
} }
}
CyclicBarrier
CyclicBarrier can be used to create a set of Children Threads if the size of the Threads created is known forehand. CyclicBarrier can be used to implement waiting amongst Children Threads until all of them finish. This is useful where parallel threads needs to perform a job which requires sequential execution. For example 10 Threads doing steps 1, 2, 3, but all 10 Threads should finish step one before any can do step 2. Cyclic barrier can be reset after all Threads are finished execution. This is a distinguishing feature from a CountDownLatch. A CountDownLatch can only be used for a single count down. Additionally a CyclicBarrier can be assigned an Additional Thread which executes each time all the Children Threads finish their respective tasks.
Practical Example : Processing of a Image Pixels Matrix row by row in the first step and in the second step saving the Pixel values to file row by row. In this scenario if there are 10 Threads running simultaneously to process the matrix row by row then all 10 should wait until all are finished before they move on to the next step which is saving those rows to file.
import java.util.concurrent.*;
import java.util.*;
import java.text.*;
/**
* @author Shazin Sadakath
*
*/
public class CyclicBarrierTest {
private static final int MAX_THREADS = 5; public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(MAX_THREADS, new Runnable() {
private int count = 1; public void run() {
System.out.printf("Cyclic Barrier Finished %d\n", count++);
}
}); System.out.println("Spawning Threads");
for(int i=0;i<MAX_THREADS;i++) {
Thread t = new Thread(new WorkerThread(cyclicBarrier, String.format("Thread-%d", i)));
t.start();
}
System.out.println("Spawning Finished");
} private static class WorkerThread implements Runnable {
private CyclicBarrier cyclicBarrier; private String name; public WorkerThread(CyclicBarrier cyclicBarrier, String name) {
this.name = name;
this.cyclicBarrier = cyclicBarrier;
} public void run() {
try {
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
System.out.printf("%s : Doing Step 1 Work on %s\n", getFormattedDate(sdf), name);
Thread.sleep(getRandomWaitTime());
System.out.printf("%s : Doing Step 1 more work on %s\n", getFormattedDate(sdf), name);
Thread.sleep(getRandomWaitTime());
System.out.printf("%s : Finished Step 1 work on %s\n", getFormattedDate(sdf), name);
int count = cyclicBarrier.await(); // Await returns an int which is the arrival index 1 means first 0 means last
System.out.printf("%s : Cyclic Barrier count on %s is %d\n", getFormattedDate(sdf), name, count);
if(count == 0) {
cyclicBarrier.reset();
}
System.out.printf("%s : Doing Step 2 Batch of Work on %s\n", getFormattedDate(sdf), name);
Thread.sleep(getRandomWaitTime());
System.out.printf("%s : Doing Some more Step 2 Batch of work on %s\n", getFormattedDate(sdf), name);
Thread.sleep(getRandomWaitTime());
System.out.printf("%s : Finished Step 2 Batch of work on %s\n", getFormattedDate(sdf), name);
count = cyclicBarrier.await();
System.out.printf("%s : Cyclic Barrier count end of Step 2 Batch of work on %s is %d\n", getFormattedDate(sdf), name, count);
} catch(Exception e) {
e.printStackTrace();
}
} private String getFormattedDate(SimpleDateFormat sdf) {
return sdf.format(new Date());
} private int getRandomWaitTime() {
return (int) ((Math.random() + 1) * 1000);
} }
}
Semaphore
Semaphore can be used to create a set of Children Threads even when the size of the Threads to be created is not known forehand. This is because a Semaphore can wait until a number of releases have been made but that number is not required to initialize the Semaphore. Semaphores can be used in other scenarios such as Synchronizing between different threads such as Publisher, Subscriber scenario.
Practical Example : Traversing through a folder with sub folders within sub folders and if JPEG files are found, move them to a destination directory and then zip them. In this scenario the folder traversing is done recursively until a JPEG file is found. And then a Thread is invoked to move it to destination directory. But zipping needs to wait until all JPEG files are moved to the destination directory. In this scenario no of JPEG files available in the folder structure is not known but the zipping needs to wait till all files are successfully moved. Ideal scenario for a Semaphore based waiting.
import java.util.concurrent.*;
import java.util.*;
import java.text.*;
/**
* @author Shazin Sadakath
*
*/
public class SemaphoreTest {
private static final int MAX_THREADS = 5; public static void main(String[] args) throws Exception {
Semaphore semaphore = new Semaphore(0); System.out.println("Spawning Threads");
int threadCount = 0;
Random random = new Random();
for(int i=0;i<MAX_THREADS;i++) {
// Threads created will not always be MAX_THREADS
// Because Threads are created only if Random no is Even.
// Thus the No of Threads unknown at Semaphore Initialization
if(random.nextInt(9999) % 2 == 0) {
Thread t = new Thread(new WorkerThread(semaphore, String.format("Thread-%d", i)));
t.start();
threadCount++;
}
}
System.out.println("Spawning Finished");
System.out.println("Waiting All Threads to Finish");
semaphore.acquire(threadCount);
System.out.println("All Threads are Finished");
} private static class WorkerThread implements Runnable {
private Semaphore semaphore; private String name; public WorkerThread(Semaphore semaphore, String name) {
this.name = name;
this.semaphore = semaphore;
} public void run() {
try {
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
System.out.printf("%s : Doing Some Work on %s\n", getFormattedDate(sdf), name);
Thread.sleep(getRandomWaitTime());
System.out.printf("%s : Doing Some more work on %s\n", getFormattedDate(sdf), name);
Thread.sleep(getRandomWaitTime());
System.out.printf("%s : Finished work on %s\n", getFormattedDate(sdf), name);
semaphore.release();
} catch(Exception e) {
e.printStackTrace();
}
} private String getFormattedDate(SimpleDateFormat sdf) {
return sdf.format(new Date());
} private int getRandomWaitTime() {
return (int) ((Math.random() + 1) * 1000);
} }
}
CountDownLatch, CyclicBarrier and Semaphore的更多相关文章
- CountDownLatch CyclicBarrier和 Semaphore
CountDownLatch CyclicBarrier和 Semaphore 原理 基于AQS实现. 让需要的暂时阻塞的线程,进入一个死循环里面,得到某个条件后再退出循环,以此实现阻塞当前线程的效果 ...
- Java并发编程:CountDownLatch、CyclicBarrier和Semaphore
Java并发编程:CountDownLatch.CyclicBarrier和Semaphore 在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch ...
- 并发工具类:CountDownLatch、CyclicBarrier、Semaphore
在多线程的场景下,有些并发流程需要人为来控制,在JDK的并发包里提供了几个并发工具类:CountDownLatch.CyclicBarrier.Semaphore. 一.CountDownLatch ...
- Java并发(8):CountDownLatch、CyclicBarrier、Semaphore、Callable、Future
CountDownLatch.CyclicBarrier.Semaphore.Callable.Future 都位于java.util.concurrent包下,其中CountDownLatch.C ...
- 【Java多线程】JUC包下的工具类CountDownLatch、CyclicBarrier和Semaphore
前言 JUC中为了满足在并发编程中不同的需求,提供了几个工具类供我们使用,分别是CountDownLatch.CyclicBarrier和Semaphore,其原理都是使用了AQS来实现,下面分别进行 ...
- CountDownLatch、CyclicBarrier和Semaphore
转载:http://www.cnblogs.com/dolphin0520/p/3920397.html 在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDown ...
- 使用Java辅助类(CountDownLatch、CyclicBarrier、Semaphore)并发编程
在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch,CyclicBarrier和Semaphore,今天我们就来学习一下这三个辅助类的用法 一.C ...
- Java并发之CountDownLatch、CyclicBarrier和Semaphore
CountDownLatch 是能使一组线程等另一组线程都跑完了再继续跑:CyclicBarrier 能够使一组线程在一个时间点上达到同步,可以是一起开始执行全部任务或者一部分任务. CountDow ...
- CountDownLatch、CyclicBarrier、Semaphore共同之处与区别以及各自使用场景
区别 CountDownLatch 使一个线程A或是组线程A等待其它线程执行完毕后,一个线程A或是组线程A才继续执行.CyclicBarrier:一组线程使用await()指定barrier,所有线程 ...
随机推荐
- 老李分享:使用 Python 的 Socket 模块开发 UDP 扫描工具
老李分享:使用 Python 的 Socket 模块开发 UDP 扫描工具 poptest是业内唯一的测试开发工程师培训机构,测试开发工程师主要是为测试服务开发测试工具,在工作中要求你做网络级别的安全 ...
- 手机自动化测试:appium源码分析之bootstrap九
手机自动化测试:appium源码分析之bootstrap九 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣, ...
- java基础--动态代理实现与原理详细分析
关于Java中的动态代理,我们首先需要了解的是一种常用的设计模式--代理模式,而对于代理,根据创建代理类的时间点,又可以分为静态代理和动态代理. 一.代理模式 ...
- ThinkPHP框架前后台的分页调用
一般ThinkPHP框架在底层给开发者提供了一个基本的分页类Page.class.php里面规定了Page类的一些基本的参数和结构. 2.应用分页 1> 调取文件use Think\Page; ...
- ios 获取当前ViewController
- (UIViewController*)getpresentVC:(UIWindow *)window{ if ([window.rootViewController class]==[UITabB ...
- Spring+SpringMVC+MyBatis+easyUI整合优化篇(九)数据层优化-jdbc连接池简述、druid简介
日常啰嗦 终于回到既定轨道上了,这一篇讲讲数据库连接池的相关知识,线程池以后有机会再结合项目单独写篇文章(自己给自己挖坑,不知道什么时候能填上),从这一篇文章开始到本阶段结束的文章都会围绕数据库和da ...
- 5 安装Alloc服务
cnblogs-DOC 1.服务器环境 2.安装Redis3.安装Zookeeper4.安装MPush5.安装Alloc服务6.完整测试7.常见问题 一.Linux安装Mpush-Alloc [roo ...
- 人生第一次hash
人生的第一次hash交给了模板题. 讲道理,还没有别人快排要快,就比暴力快那么一点... 难道我写的hash就那么菜么? 我想了想,光是处理字符串就O(n*len).. 这是hash的正确写法吗?我都 ...
- JS取消浏览器文本选中的方法
一 .问题的出现 今天在使用Easy-UI 的messager.alert()方法时候出现浏览器文本被选中,不知道其中是什么原因,如下图所示. 二 .解决思路 我最后的思路时在弹出消息框的同时,取消浏 ...
- Tomcat access log配置
在tomcat的access中打印出请求的情况可以帮助我们分析问题,通常比较关注的有访问IP.线程号.访问url.返回状态码.访问时间.持续时间. 在Spring boot中使用了内嵌的tomcat, ...