java.concurrency CyclicBarrier and CountdownLatch: What’s the difference?

I have been researching the Java concurrency classes added as a part of the Java Tiger release. The CyclicBarrier and CountdownLatch classes appeared to achieve the same effect or so to speak provide the same functionality. A bit of further digging revealed the difference.

Here’s a sample WorkerThread implemented to understand the functioning of CyclicBarrier.

package com.java.concurrency.barrier;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class WorkerThread implements Runnable {

	private CyclicBarrier barrier = null;
	private int name = 0;
	
	public WorkerThread(CyclicBarrier barrier, int name) {
		this.barrier = barrier;
		this.name = name;
	}
	
	public void run() {
		DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
		String s = fmt.format(new Date());
		System.out.println(s+"=Doing some work for thread: " + this.name);
		try {
			Thread.sleep(name*1000);
			s = fmt.format(new Date());
			System.out.println(s+"=Work done for thread: " + this.name);
			int count = barrier.await();
			s = fmt.format(new Date());
			System.out.println(s+"=Inside thread " + this.name + " count is " + count);
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (BrokenBarrierException e) {
			e.printStackTrace();
		}
	}
}

I use the following test class to run the WorkerThread.

package com.java.concurrency.barrier;

import java.util.concurrent.CyclicBarrier;

public class BarrierTest {

	public static void main(String[] args) {
		CyclicBarrier barrier = new CyclicBarrier(3);
		
		for (int i=0; i<3; i++) {
			Thread t = new Thread(new WorkerThread(barrier, i));
			t.start();
		}
	}
}

Here’s the output generated:

2010-10-08 10:28:13:014=Doing some work for thread: 2
2010-10-08 10:28:13:014=Doing some work for thread: 1
2010-10-08 10:28:13:014=Doing some work for thread: 0
2010-10-08 10:28:13:014=Work done for thread: 0
2010-10-08 10:28:14:016=Work done for thread: 1
2010-10-08 10:28:15:019=Work done for thread: 2
2010-10-08 10:28:15:019=Inside thread 0 count is 2
2010-10-08 10:28:15:019=Inside thread 1 count is 1
2010-10-08 10:28:15:019=Inside thread 2 count is 0

I have specifically added the SimpleDateFormat code to capture the timing details and highlight some aspects of the code run. From the output it is clear that the threads run up-to the barrier.await() invocation line(Line: 27) and suspend their operations until barrier’s await() method is invoked three times. This is the limit we have defined in the during CyclicBarrier’s construction (Line: 8). Once the await method is invoked thrice, all the threads proceed with their respective processing.

Now to understand the functioning of CountdownLatch refer the following WorkerThread class.

package com.java.concurrency.latch;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.CountDownLatch;

public class WorkerThread implements Runnable {

	private CountDownLatch latch = null;
	private int name = 0;
	
	public WorkerThread(CountDownLatch latch, int name) {
		this.latch = latch;
		this.name = name;
	}

	
	public void run() {
		DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
		String s = fmt.format(new Date());
		System.out.println(s+"=Doing some work for thread: " + this.name);
		try {
			Thread.sleep(name*1000);
			s = fmt.format(new Date());
			System.out.println(s+"=Work done for thread: " + this.name);
			latch.countDown();
			s = fmt.format(new Date());
			System.out.println(s+"=Inside thread " + this.name);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}

The source code of the CountdownLatch worker thread is exactly the same as that of CyclicBarrier except for the concurrency class in use. Here’s the test class:

package com.java.concurrency.latch;

import java.util.concurrent.CountDownLatch;

public class CountdownLatchTest {

	public static void main(String[] args) {
		CountDownLatch latch = new CountDownLatch(3);
		
		for(int i=0; i<3; i++) {
			Thread t = new Thread(new WorkerThread(latch, i));
			t.start();
		}
		try {
			latch.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(&quot;Done with latch processing.&quot;);
	}
}

The output generated is as follows:

2010-10-08 10:46:55:496=Doing some work for thread: 1
2010-10-08 10:46:55:496=Doing some work for thread: 0
2010-10-08 10:46:55:496=Doing some work for thread: 2
2010-10-08 10:46:55:496=Work done for thread: 0
2010-10-08 10:46:55:496=Inside thread 0
2010-10-08 10:46:56:498=Work done for thread: 1
2010-10-08 10:46:56:498=Inside thread 1
2010-10-08 10:46:57:501=Work done for thread: 2
2010-10-08 10:46:57:501=Inside thread 2
Done with latch processing.

Here the thread runs does not stop but continue unabated after invoking countDown() method. The latch does provide an await method which I could use on the main thread to suspend it until the individual thread processing is complete. This is the key difference between CyclicBarrier and CountdownLatch. CyclicBarrier makes sense in scenarios where the end user wants to ensure that multiple threads do their individual processing up-to a certain point and then wait for their colleagues to complete their processing. The class is named “cyclic” because it can be reused after the waiting threads are released. CountdownLatch on the other hand make sense for applications where the individual threads can countdown and proceed with their activities.

Advertisements

6 thoughts on “java.concurrency CyclicBarrier and CountdownLatch: What’s the difference?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s