Reference:

[1] http://shazsterblog.blogspot.co.uk/2011/12/comparison-of-countdownlatch.html

CountDownLatch vs CyclicBarrier

  1. CountDownLatch can not be reused after meeting the final count.

  2. CountDownLatch can not be used to wait for Parallel Threads to finish.

  3. CyclicBarrier can be reset thus reused

  4. 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的更多相关文章

  1. CountDownLatch CyclicBarrier和 Semaphore

    CountDownLatch CyclicBarrier和 Semaphore 原理 基于AQS实现. 让需要的暂时阻塞的线程,进入一个死循环里面,得到某个条件后再退出循环,以此实现阻塞当前线程的效果 ...

  2. Java并发编程:CountDownLatch、CyclicBarrier和Semaphore

    Java并发编程:CountDownLatch.CyclicBarrier和Semaphore 在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch ...

  3. 并发工具类:CountDownLatch、CyclicBarrier、Semaphore

    在多线程的场景下,有些并发流程需要人为来控制,在JDK的并发包里提供了几个并发工具类:CountDownLatch.CyclicBarrier.Semaphore. 一.CountDownLatch ...

  4. Java并发(8):CountDownLatch、CyclicBarrier、Semaphore、Callable、Future

    CountDownLatch.CyclicBarrier.Semaphore.Callable.Future  都位于java.util.concurrent包下,其中CountDownLatch.C ...

  5. 【Java多线程】JUC包下的工具类CountDownLatch、CyclicBarrier和Semaphore

    前言 JUC中为了满足在并发编程中不同的需求,提供了几个工具类供我们使用,分别是CountDownLatch.CyclicBarrier和Semaphore,其原理都是使用了AQS来实现,下面分别进行 ...

  6. CountDownLatch、CyclicBarrier和Semaphore

    转载:http://www.cnblogs.com/dolphin0520/p/3920397.html 在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDown ...

  7. 使用Java辅助类(CountDownLatch、CyclicBarrier、Semaphore)并发编程

    在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch,CyclicBarrier和Semaphore,今天我们就来学习一下这三个辅助类的用法 一.C ...

  8. Java并发之CountDownLatch、CyclicBarrier和Semaphore

    CountDownLatch 是能使一组线程等另一组线程都跑完了再继续跑:CyclicBarrier 能够使一组线程在一个时间点上达到同步,可以是一起开始执行全部任务或者一部分任务. CountDow ...

  9. CountDownLatch、CyclicBarrier、Semaphore共同之处与区别以及各自使用场景

    区别 CountDownLatch 使一个线程A或是组线程A等待其它线程执行完毕后,一个线程A或是组线程A才继续执行.CyclicBarrier:一组线程使用await()指定barrier,所有线程 ...

随机推荐

  1. webdriver介绍&与Selenium RC的比较

    什么是webdriver? webdriver是一个web自动化测试框架,不同于selenium IDE只能运行在firefox上,webdriver能够在不同的浏览器上执行你的web测试用例.其支持 ...

  2. 服务器上的Git

    前面的话 如果想与他人使用,除了使用Git来完成日常工作之外,还需要一个远程的Git仓库.尽管从技术上可以从个人的仓库里推送和拉取修改内容,但并不鼓励这样做,因为一不留心就很容易弄混其他人的进度.因此 ...

  3. 关于php 高并发解决的一点思路

    涉及抢购.秒杀.抽奖.抢票等活动时,为了避免超卖,那么库存数量是有限的,但是如果同时下单人数超过了库存数量,就会导致商品超卖问题.那么我们怎么来解决这个问题呢,我的思路如下(伪代码): sql1:查询 ...

  4. 第一章 自定义MVC框架

    第一章  自定义MVC框架1.1 MVC模式设计    组成:Model:模型,用于数据和业务的处理          View :视图,用于数据的显示          Controller:控制器 ...

  5. html 选择器之属性选择器

    属性选择器的主要作用个人的理解就是对带有指定属性的元素设置css样式. 使用css3的属性选择器,可以指定元素的某个属性,也可以指定某个属性和这个属性所对应的值. css3的属性选择器主要包括下面几种 ...

  6. Spring Cloud搭建微服务架构----前言

    前言 微服务并不神秘,只是在互联网技术发展过程中的一个产物,整个架构系统随着客户端的多样性,服务越来越多,devops的发展而产生的架构变种. 许多公司,通过采用微处理结构模式解决单体应用的问题,分解 ...

  7. MySQL最常用数值函数

    数值函数: 用来处理很多数值方面的运算,使用数值函数,可以免去很多繁杂的判断求值的过程,能够大大提高用户的工作效率. 1.ABS(x):返回 x 的绝对值 mysql> select abs(- ...

  8. 有关 json对象 取出其中数据问题

    这几天,在做一个ajax异步提交的小功能,发现从ashx中传递过来的string 类型的数据,一直拿不到(当时是指的是json点不出来),傻傻的自己,一直在找其他的方法,看看其他那里出了错误,最后,那 ...

  9. java 集合框架(TreeSet操作,自动对数据进行排序,重写CompareTo方法)

    /*TreeSet * treeSet存入数据后自动调用元素的compareTo(Object obj) 方法,自动对数据进行排序 * 所以输出的数据是经过排序的数据 * 注:compareTo方法返 ...

  10. 【2017-04-25】winform公共控件、菜单和工具栏、Tab和无边框窗体制作

    一.公共控件 1. Button   按钮 + 布局 - AutoSize   按钮尺寸自动适应里面内容的长度 - Location    位置 - Margin       控件与控件外边距 - S ...