I have a list which needs to be populated by three parties(threads,lets say).I am using cyclic barrier to achieve this functionality. Everything works fine except that I am not able to use the resulted list without inducing a forced sleep. Below is the code :
public class Test{
List<Integer> item = new Vector<Integer>();
public void returnTheList(){
CyclicBarrier cb = new CyclicBarrier(3, new Runnable() {
@Override
public void run() {
System.out.println("All parties are arrived at barrier, lets play -- : " + CyclicBarrierTest.getTheList().size());
//Here I am able to access my resulted list
}
});
CyclicBarrierTest sw1 = new CyclicBarrierTest(cb, new ZetaCode(1500), s);
CyclicBarrierTest sw2 = new CyclicBarrierTest(cb, new ZetaCode(1500),s);
CyclicBarrierTest sw3 = new CyclicBarrierTest(cb, new ZetaCode(1500),s);
Thread th1 = new Thread(sw1, "ZetaCode1");
Thread th2 = new Thread(sw2, "ZetaCode2");
Thread th3 = new Thread(sw3, "ZetaCode3");
th1.start();
th2.start();
th3.start();
}
public static void main(String args[]){
System.out.println("asdfasd");
Test test = new Test();
//ActionClass ac = new ActionClass();
test.returnTheList();
System.out.println("Inside the main method...size of the final list : " +test.item.size() );
}
Below is my CyclicBrrierTest class :
public class CyclicBarrierTest implements Runnable{
private CyclicBarrier barrier;
private Object obj;
static volatile String s = "";
volatile List<Integer> finalIntList = new Vector<Integer>();
public CyclicBarrierTest(CyclicBarrier barrier, Object obj, String s){
this.barrier = barrier;
this.obj = obj;
}
@Override
public void run(){
try{
System.out.println(Thread.currentThread().getName() + " is waiting on barrier and s is now : " + finalIntList.size());
ZetaCode simple = (ZetaCode)obj;
finalIntList.addAll(simple.getTheItemList());
barrier.await();
System.out.println(Thread.currentThread().getName() + " has crossed the barrier");
}catch(InterruptedException ex){
System.out.println("Error.." + ex.getMessage());
}catch(Exception e){
System.out.println("Error.." + e.getMessage());
}
}
public List<Integer> getTheList(){
return finalIntList;
}
So if I run this code without giving any delay the print statement in my main method gives me the length of my list as zero,however after giving an appropriate sleep it gives me the expected output.I want to achieve the same without giving any delay.Any help would be appreciated. Thanks in advance.
It seems you'd want to use a CountDownLatch
, not a CyclicBarrier
here. The CyclicBarrier
is working exactly as intended - your main method just isn't waiting for it to be tripped by all 3 threads. When you give it a sleep statement, the other 3 threads just happen to finish before main
wakes up again.
A CyclicBarrier
is useful when you need N
workers to all reach the same 'checkpoint' before proceeding, and the workers themselves are the only ones who care. However, you have an N + 1
user here, the main
thread, who wants to know when they're all done, and CyclicBarrier
doesn't support that use case.
Note, of course that you can also use both of them.