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. 老李推荐:第14章5节《MonkeyRunner源码剖析》 HierarchyViewer实现原理-装备ViewServer-查询ViewServer运行状态

    老李推荐:第14章5节<MonkeyRunner源码剖析> HierarchyViewer实现原理-装备ViewServer-查询ViewServer运行状态   poptest是国内唯一 ...

  2. android开发之-软件设置保存-快速学会使用SharedPreferences篇-实测

    我们在设计软件的时候,需要记录软件设置的基本信息,那么怎么来保存他们呢?我们可以使用SharedPreferences.   SharedPreferences是一个xml文件,用来存储软件的常规设置 ...

  3. JavaScript高级程序设计---学习笔记(三)

    函数表达式 定义函数的方式有两种:一种是函数声明,另一种是函数表达式. 关于函数声明,它的一个重要特征就是函数声明提升,意思是在执行代码之前会先读取函数声明所以可以把函数声明放在调用它的语句后面. 而 ...

  4. 【G】开源的分布式部署解决方案文档 - 部署Console & 控制负载均衡 & 跳转持续集成控制台

    G.系列导航 [G]开源的分布式部署解决方案 - 导航 设置项目部署流程 项目类型:选择Console,这个跟功能无关,只是做项目分类,后面会有后续功能 宿主:选择Console 部署方式:选择原始, ...

  5. weex里Vuex state使用storage持久化

    在weex里使用Vuex作为state管理工具,问题来了,如何使得state可以持久化呢?weex官方提供store模块,因此我们可以尝试使用该模块来持久化state. 先看下该模块介绍: stora ...

  6. Virtualbox 复制 CentOS 虚拟机无法联网

    Centos刚装好后无法联网 复制虚拟机后,出现 No such device eth0 我们要处理的三个问题: 在Virtualbox上安装好Centos后如何联网 如何在Virtualbox上复制 ...

  7. Java多线程学习笔记(二)——Executor,Executors,ExecutorService比较

    Executor:是Java线程池的超级接口:提供一个execute(Runnable command)方法;我们一般用它的继承接口ExecutorService. Executors:是java.u ...

  8. 详解Executor框架

    在Java中,使用线程来异步执行任务.Java线程的创建与销毁需要一定的开销,如果我们为每一个任务创建一个新线程来执行,这些线程的创建与销毁将消耗大量的计算资源.同时,为每一个任务创建一个新线程来执行 ...

  9. js 解析本地Excel文件!

    通常,一般读取Excel都是由后台来处理,不过如果需求要前台来处理,也是可以的.. 1.需要用到js-xlsx,下载地址:js-xlsx 2.demo: <!DOCTYPE html>&l ...

  10. ajax发送异步请求

    一:得到XMLHttpRequest对象 ajax其实只需要学习XMLHttpRequest一个对象 大多数浏览器都支持: var xmlHttp = new XMLHttprequest(); IE ...