一、CountDownLatch
相当于go里面的sync.waitGroup
构造方法传入计数器的值,线程结束后调用countDown()方法使得计数器-1,主线程调用await()方法阻塞等待计数器到0
二、CyclicBarrier
CyclicBarrier相当于一个阶段性的CountDownLatch
构造方法:
public CyclicBarrier(int parties, Runnable barrierAction)
public CyclicBarrier(int parties) {
this(parties, null);
}
每个线程都需要调用await()来阻塞本线程的继续运行,当所有线程都到达await()点后,会由最后一个达到await()点的线程执行barrierAction,然后所有线程继续往下运行,parties又设置为初始值,迎接下一个屏障点
例子:
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
class MyThread extends Thread {
private CyclicBarrier cb;
public MyThread(String name, CyclicBarrier cb) {
super(name);
this.cb = cb;
}
public void run() {
System.out.println(Thread.currentThread().getName() + " going to await");
try {
cb.await();
System.out.println(Thread.currentThread().getName() + " continue");
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class CyclicBarrierDemo {
public static void main(String[] args) throws InterruptedException, BrokenBarrierException {
CyclicBarrier cb = new CyclicBarrier(3, new Thread("barrierAction") {
public void run() {
System.out.println(Thread.currentThread().getName() + " barrier action");
}
});
MyThread t1 = new MyThread("t1", cb);
MyThread t2 = new MyThread("t2", cb);
t1.start();
t2.start();
System.out.println(Thread.currentThread().getName() + " going to await");
cb.await();
System.out.println(Thread.currentThread().getName() + " continue");
}
}
可能的输出:
t1 going to await
main going to await
t2 going to await
// t2最后达到await
t2 barrier action
// 所有线程继续执行
t2 continue
t1 continue
main continue
破坏屏障可以用breakBarrier(),会唤醒所有在屏障中的线程
三、CountDownLatch和CyclicBarrier的区别
1、CountDownLatch减计数,CyclicBarrier加计数。
2、CountDownLatch是一次性的,CyclicBarrier可以重用。
3、CountDownLatch和CyclicBarrier都有让多个线程等待同步然后再开始下一步动作的意思,但是CountDownLatch的下一步的动作实施者是主线程,具有不可重复性;而CyclicBarrier的下一步动作实施者还是“其他线程”本身,具有往复多次实施动作的特点。