概念
CyclicBarrier:假设有这么一个场景:每一个线程代表一个跑步运动员,当运动员都准备好后,才一起出发,只要有一个人没准备好,大家都在等待。
CountDownLacth:他经常用于监听某些初始化操作,等初始化执行完毕后,通知主线程继续工作。
事例
CountDownLacth的使用
public class UseCountDownLatch {
public static void main(String[] args) {
final CountDownLatch countDown=new CountDownLatch(2);
Thread t1=new Thread(new Runnable(){
@Override
public void run() {
try {
System.out.println("进入线程1并等待其他线程完成......");
countDown.await();
System.out.println("t1线程继续执行....");
} catch (Exception e) {
e.printStackTrace();
}
}
},"t1");
Thread t2=new Thread(new Runnable(){
@Override
public void run() {
try {
System.out.println("线程2进行初始化操作");
Thread.sleep(3000);
System.out.println("线程2进行初始化完毕,通知t1线程继续");
countDown.countDown();
} catch (Exception e) {
e.printStackTrace();
}
}
},"t2");
Thread t3=new Thread(new Runnable(){
@Override
public void run() {
try {
System.out.println("线程3进行初始化操作");
Thread.sleep(3000);
System.out.println("线程3进行初始化完毕,通知t1线程继续");
countDown.countDown();
} catch (Exception e) {
e.printStackTrace();
}
}
},"t3");
t1.start();
t2.start();
t3.start();
}
}
运行结果
其中这行代码很关键,之所以要声明成final,是因为他被匿名内部类引用了,参数是2说明必须调用两次countDown.countDown()才能把countDown.await()唤醒。所以这里线程2,线程3都调用了countDown.countDown()才把线程1唤醒,缺一不可。
final CountDownLatch countDown=new CountDownLatch(2);
CyclicBarrier的使用
public class UseCyclicBarrier {
static class Runner implements Runnable{
private CyclicBarrier barrier;
private String name;
public Runner(CyclicBarrier barrier,String name){
this.barrier=barrier;
this.name=name;
}
@Override
public void run() {
try {
Thread.sleep(1000*(new Random()).nextInt(5));
System.out.println(name+"准备好了");
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(name+"GO!!!");
}
}
public static void main(String[] args) {
CyclicBarrier barrier=new CyclicBarrier(3);
ExecutorService executor=Executors.newFixedThreadPool(3);
executor.execute(new Thread(new Runner(barrier,"张三")));
executor.execute(new Thread(new Runner(barrier,"李四")));
executor.execute(new Thread(new Runner(barrier,"王五")));
executor.shutdown();
}
}
运行结果:先打印了张三准备好了,过几秒打印了王五准备好了,过几秒后后面的一起打印了。
参数3说明,barrier.await()必须调用三次后,才会分别执行各自barrier.await()后的语句
CyclicBarrier barrier=new CyclicBarrier(3);