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. Java面试步步走

    一.Java 基础 1.Java 集合原理 2.Java 多线程.同步集合.并发集合.阻塞队列.线程池.各种锁等 3.JVM 垃圾回收机制.JVM 引用类型.JVM 内存模型 二.应用技术基础 1)数 ...

  2. 关于WdatePicker.js的结束时间大于开始时间

    简单笔记 : WdatePicker.js 要使结束时间大于开始时间只要在线束时间的 minDate:'#F{$dp.$D(\'stimeParam\')}' 即可:不多说 详细代码如下: <t ...

  3. Entity Framework快速入门--IQueryable与IEnumberable的区别

    IEnumerable接口 公开枚举器,该枚举器支持在指定类型的集合上进行简单迭代.也就是说:实现了此接口的object,就可以直接使用foreach遍历此object: IQueryable 接口 ...

  4. sublime text3 在ubutun下的下载和配置

    最近在学习 Javascript,在 w3c school 上把教程看完了,也算个刚刚入门的水平,一直都是在 win 系统 上练习. 但是因为写 python 代码的 pycharm 和 git 配置 ...

  5. Web worker 与JS中异步编程的对比

    0.从一道题说起 var t = true; setTimeout(function(){ t = false; }, 1000); while(t){ } alert('end'); 问,以上代码何 ...

  6. 对quartz定时任务的初步认识

    已经好久没有写技术博文了,今天就谈一谈我前两天自学的quartz定时任务吧,我对quartz定时任务的理解,就是可以设定一个时间,然后呢,在这个时间到的时候,去执行业务逻辑,这是我的简单理解,接下来看 ...

  7. 3 安装Zookeeper

    cnblogs-DOC 1.服务器环境 2.安装Redis3.安装Zookeeper4.安装MPush5.安装Alloc服务6.完整测试7.常见问题 从官网直接下载Zookeeper最新版本(Zook ...

  8. 用 js 的 selection range 操作选择区域内容和图片

    原创文章,转载请注明出处并保留地址.原文地址:http://www.cnblogs.com/muge10/p/6723894.html 最近在做编辑器相关的东西,遇到一个需求,用户在编辑器中插入或者粘 ...

  9. Anaconda配置多spyder多python环境

    作者:桂. 时间:2017-04-17  22:02:37 链接:http://www.cnblogs.com/xingshansi/p/6725298.html  前言 最近在看<统计学习方法 ...

  10. JavaWeb开发之HttpServletResponse

    1. HttpServletResponse简介 Web服务器回送给Web客户端的HTTP响应消息分为三个部分:状态行,响应消息头,响应体. Servlet API中定义了ServletRespons ...