Saturday 27 February 2010

Java Concurrency - Use of CountDownLatch

CountDownLatch allows one or more threads to wait until a set of operations being performed in other threads completes. A CountDownLatch is initialized with a given count.
E.g. suppose you have Birthday party, and then the following activities must happen in a given order.
1. Get the Cake.
2. Put the (N) candles and light them.
3. Blow and Sing a song.

So in such situation, we can utilize CountDownLatch to perform above tasks in order.

To achive this, I have created three Runables

1. GetCake – Initialized with count 1. It acts as ON/OFF switch
2. PutCandles - Initialized with count 10, as we are putting 10 candles on Cake
3. BlowAndSing – Does not require as it is the last task in the sequence.

Once GetCake task is done, it notifies PutCandles . Once PutCandles is done(for 10 candles), it notifies BlowAndSing .
Following is the code sample :



import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class TestCountDownLatch1 {

public static void main(String[] args) {
TestCountDownLatch1 cdl1 = new TestCountDownLatch1();
cdl1.test();
}

private void test() {
CountDownLatch gotTheCake = new CountDownLatch(1);
CountDownLatch candlesReady = new CountDownLatch(10);

ExecutorService es = Executors.newFixedThreadPool(15);
Runnable task = null;

task = new GetCake(gotTheCake);
es.execute(task);

for(int i=1; i<= 10; i++) {
task = new PutCandles(i, gotTheCake, candlesReady, i);
es.execute(task);
}

task = new BlowAndSing(candlesReady);
es.execute(task);

es.shutdown();
}

}

class PutCandles implements Runnable {

CountDownLatch gotTheCake;
CountDownLatch candlesReady;
private int candleNo;
int sleepTime;

public PutCandles(int candleNo, CountDownLatch gotTheCake, CountDownLatch candlesReady, int sleepTime) {
this.candleNo = candleNo;
this.gotTheCake = gotTheCake;
this.candlesReady = candlesReady;
this.sleepTime = sleepTime;
}
@Override
public void run() {
try {
gotTheCake.await();
Thread.sleep(sleepTime * 1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

System.out.println("Putting candle no : "+ candleNo+ " and lighting it.");
candlesReady.countDown();
}
}

class GetCake implements Runnable {

CountDownLatch gotTheCake;

public GetCake(CountDownLatch gotTheCake) {
this.gotTheCake = gotTheCake;
}
@Override
public void run() {
System.out.println("Got the Cake : ");
gotTheCake.countDown();
}
}

class BlowAndSing implements Runnable {

CountDownLatch candlesReady;

public BlowAndSing(CountDownLatch candlesReady) {
this.candlesReady = candlesReady;
}
@Override
public void run() {
try {
candlesReady.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Fuuuuuuuuuuu..Happy B'day Soham...:) ");
}
}



No comments: