CountDownLatch
CountDownLatch这个类使一个线程等待其他线程完成各自的工作再执行,例如主线程希望子线程完成操作后让自线程使用。
CountDownLatch是通过计数器实现,每次完成一个任务后,计数器减一当为0时,CountDownLatch.await()方法的线程就可以恢复执行任务。
如图我们Tw1线程Tw2线程 执行了await方法 进行等待,这是countDownlotch设置为5,ta、tb、tc、td调用countDown方法让计数器减一,当计数器为0时,Tw1、Tw2线程恢复运行。
注意:不是子countdownlatch不是线程的数量、而且当countdownchlatch不等于线程数
public class UseCountDownLatch {
static CountDownLatch latch = new CountDownLatch(4);
private static class InitThread implements Runnable{
public void run() {
System.out.println("Thread_"+Thread.currentThread().getId()
+" ready init work......");
latch.countDown();
}
}
public static void main(String[] args) throws InterruptedException {
new Thread(new BusiThread()).start();
for(int i=0;i<=3;i++){
Thread thread = new Thread(new InitThread());
thread.start();
}
latch.await();
System.out.println("Main do ites work........");
}
}
demo中演示的是一段 开启四个子线程,主线程调用await进入阻塞状态,调用countDown方法,当countdownchlatch为0时,主线程阻塞状态恢复。
CyclicBarrier
CyclicBarrier是一种线程间的屏障,一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续运行。
CyclicBarrier默认的构造方法是CyclicBarrier(int parties),其参数表示屏障拦截的线程数量,每个线程调用await方法告诉CyclicBarrier我已经到达了屏障,然后当前线程被阻塞。
CyclicBarrier还提供一个更高级的构造函数CyclicBarrier(int parties,Runnable barrierAction),用于在线程到达屏障时,优先执行barrierAction,方便处理更复杂的业务场景。
public class UseCyclicBarrier {
private static CyclicBarrier barrier
= new CyclicBarrier(4,new CollectThread());
public static void main(String[] args) {
for(int i=0;i<4;i++){
Thread thread = new Thread(new SubThread());
thread.start();
}
}
/*汇总的任务*/
private static class CollectThread implements Runnable{
@Override
public void run() {
System.out.println("do other business........");
}
}
/*相互等待的子线程*/
private static class SubThread implements Runnable{
@Override
public void run() {
long id = Thread.currentThread().getId();
resultMap.put(Thread.currentThread().getId()+"",id);
try {
Thread.sleep(1000+id);
System.out.println("Thread_"+id+" ....do something ");
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
这里我们开启了4个子线程,他们全部完成工作后,汇总线程CollectThread执行。
两者区别
CountDownLatch的计数器只能使用一次,而CyclicBarrier的计数器可以反复使用。
CountDownLatch.await一般阻塞工作线程,所有的进行预备工作的线程执行countDown,而CyclicBarrier通过工作线程调用await从而自行阻塞,直到所有工作线程达到指定屏障,再大家一起往下走。
在控制多个线程同时运行上,CountDownLatch可以不限线程数量,而CyclicBarrier是固定线程数。
同时,CyclicBarrier还可以提供一个barrierAction,合并多线程计算结果。