首先申明一下二者的主要区别
1. CountDownLatch是线程组之间的等待,即一个(或多个)线程等待N个线程完成某件事情之后再执行;
2. 而CyclicBarrier则是线程组内的等待,即每个线程相互等待,即N个线程都被拦截之后,然后依次执行。
3. CountDownLatch是减计数方式,而CyclicBarrier是加计数方式。
4. CountDownLatch计数为0无法重置,而CyclicBarrier计数达到初始值,则可以重置。
5. CountDownLatch不可以复用,而CyclicBarrier可以复用。
使用CountDownLatch和CyclicBarrier分别模拟java多线程并发
CountDownLatch
@Test
void testCountDownLatch(){
//等待100个线程同时执行
CountDownLatch countDownLatch = new CountDownLatch(100);
for(int i=0;i<100;i++){
Thread thread = new MyThread(countDownLatch);
thread.start();
countDownLatch.countDown();
}
}
static class MyThread extends Thread{
final static Logger logger = LoggerFactory.getLogger(MyThread.class);
private CountDownLatch countDownLatch;
public MyThread(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
super.run();
try {
countDownLatch.await();
logger.debug("count:{},id:{}", countDownLatch.getCount(),SyncId.getId());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-9] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:37
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-16] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:20
2020-09-27 21:33:11.785 DEBUG 18864 --- [ Thread-62] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:63
2020-09-27 21:33:11.785 DEBUG 18864 --- [ Thread-59] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:60
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-34] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:19
2020-09-27 21:33:11.785 DEBUG 18864 --- [ Thread-61] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:62
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-4] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:53
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-38] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:27
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-21] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:5
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-53] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:54
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-37] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:25
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-33] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:18
2020-09-27 21:33:11.783 DEBUG 18864 --- [ Thread-22] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:3
2020-09-27 21:33:11.786 DEBUG 18864 --- [ Thread-63] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:64
2020-09-27 21:33:11.783 DEBUG 18864 --- [ Thread-27] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:1
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-5] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:51
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-17] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:17
2020-09-27 21:33:11.785 DEBUG 18864 --- [ Thread-60] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:61
2020-09-27 21:33:11.786 DEBUG 18864 --- [ Thread-64] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:65
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-25] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:15
2020-09-27 21:33:11.786 DEBUG 18864 --- [ Thread-65] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:66
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-51] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:50
2020-09-27 21:33:11.786 DEBUG 18864 --- [ Thread-66] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:67
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-35] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:21
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-50] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:49
2020-09-27 21:33:11.783 DEBUG 18864 --- [ Thread-29] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:6
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-13] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:29
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-12] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:26
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-24] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:13
2020-09-27 21:33:11.787 DEBUG 18864 --- [ Thread-67] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:68
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-39] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:28
2020-09-27 21:33:11.785 DEBUG 18864 --- [ Thread-57] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:58
2020-09-27 21:33:11.787 DEBUG 18864 --- [ Thread-68] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:69
2020-09-27 21:33:11.788 DEBUG 18864 --- [ Thread-70] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:71
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-40] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:30
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-52] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:52
2020-09-27 21:33:11.783 DEBUG 18864 --- [ Thread-31] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:11
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-36] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:24
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-49] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:47
2020-09-27 21:33:11.788 DEBUG 18864 --- [ Thread-69] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:70
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-100] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:48
2020-09-27 21:33:11.783 DEBUG 18864 --- [ Thread-28] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:4
2020-09-27 21:33:11.783 DEBUG 18864 --- [ Thread-26] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:10
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-15] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:22
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-14] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:23
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-19] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:12
2020-09-27 21:33:11.789 DEBUG 18864 --- [ Thread-72] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:73
2020-09-27 21:33:11.788 DEBUG 18864 --- [ Thread-71] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:72
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-11] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:32
2020-09-27 21:33:11.789 DEBUG 18864 --- [ Thread-73] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:74
2020-09-27 21:33:11.783 DEBUG 18864 --- [ Thread-30] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:8
2020-09-27 21:33:11.789 DEBUG 18864 --- [ Thread-75] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:76
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-48] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:46
2020-09-27 21:33:11.783 DEBUG 18864 --- [ Thread-23] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:7
2020-09-27 21:33:11.783 DEBUG 18864 --- [ Thread-20] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:9
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-55] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:56
2020-09-27 21:33:11.790 DEBUG 18864 --- [ Thread-76] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:77
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-3] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:44
2020-09-27 21:33:11.790 DEBUG 18864 --- [ Thread-77] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:78
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-54] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:55
2020-09-27 21:33:11.790 DEBUG 18864 --- [ Thread-78] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:79
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-47] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:43
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-18] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:14
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-41] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:31
2020-09-27 21:33:11.791 DEBUG 18864 --- [ Thread-80] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:81
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-42] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:33
2020-09-27 21:33:11.785 DEBUG 18864 --- [ Thread-58] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:59
2020-09-27 21:33:11.791 DEBUG 18864 --- [ Thread-86] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:87
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-32] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:16
2020-09-27 21:33:11.791 DEBUG 18864 --- [ Thread-85] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:86
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-44] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:38
2020-09-27 21:33:11.791 DEBUG 18864 --- [ Thread-84] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:85
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-45] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:40
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-43] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:36
2020-09-27 21:33:11.791 DEBUG 18864 --- [ Thread-83] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:84
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-8] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:39
2020-09-27 21:33:11.792 DEBUG 18864 --- [ Thread-88] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:89
2020-09-27 21:33:11.792 DEBUG 18864 --- [ Thread-89] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:90
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-46] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:41
2020-09-27 21:33:11.792 DEBUG 18864 --- [ Thread-90] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:91
2020-09-27 21:33:11.792 DEBUG 18864 --- [ Thread-91] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:92
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-7] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:42
2020-09-27 21:33:11.793 DEBUG 18864 --- [ Thread-92] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:93
2020-09-27 21:33:11.793 DEBUG 18864 --- [ Thread-95] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:96
2020-09-27 21:33:11.791 DEBUG 18864 --- [ Thread-82] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:83
2020-09-27 21:33:11.791 DEBUG 18864 --- [ Thread-81] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:82
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-101] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:35
2020-09-27 21:33:11.793 DEBUG 18864 --- [ Thread-96] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:97
2020-09-27 21:33:11.793 DEBUG 18864 --- [ Thread-98] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:99
2020-09-27 21:33:11.793 DEBUG 18864 --- [ Thread-99] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:100
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-10] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:34
2020-09-27 21:33:11.790 DEBUG 18864 --- [ Thread-79] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:80
2020-09-27 21:33:11.783 DEBUG 18864 --- [ Thread-2] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:2
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-56] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:57
2020-09-27 21:33:11.789 DEBUG 18864 --- [ Thread-74] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:75
2020-09-27 21:33:11.784 DEBUG 18864 --- [ Thread-6] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:45
2020-09-27 21:33:11.793 DEBUG 18864 --- [ Thread-97] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:98
2020-09-27 21:33:11.793 DEBUG 18864 --- [ Thread-93] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:94
2020-09-27 21:33:11.793 DEBUG 18864 --- [ Thread-94] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:95
2020-09-27 21:33:11.792 DEBUG 18864 --- [ Thread-87] d.m.BlogMybatisApplicationTests$MyThread : count:0,id:88
783-793 将近10ms这100线程才都执行完
CyclicBarrier
@Test
void test01(){
CyclicBarrier cyclicBarrier = new CyclicBarrier(100);
for(int i=0;i<100;i++){
Thread thread = new MyThread01(cyclicBarrier);
thread.start();
}
}
static class MyThread01 extends Thread{
final static Logger logger = LoggerFactory.getLogger(MyThread01.class);
private CyclicBarrier cyclicBarrier;
public MyThread01(CyclicBarrier cyclicBarrier) {
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run() {
super.run();
try {
cyclicBarrier.await();
logger.debug("numberWait:{},id:{}", cyclicBarrier.getNumberWaiting(),SyncId.getId());
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
}
CyclicBarrier实例二
public class CyclicBarrierDemo {
static class TaskThread extends Thread {
CyclicBarrier barrier;
public TaskThread(CyclicBarrier barrier) {
this.barrier = barrier;
}
@Override
public void run() {
try {
Thread.sleep(1000);
System.out.println(getName() + " 到达栅栏 A");
barrier.await();
System.out.println(getName() + " 冲破栅栏 A");
Thread.sleep(2000);
System.out.println(getName() + " 到达栅栏 B");
barrier.await();
System.out.println(getName() + " 冲破栅栏 B");
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
int threadNum = 5;
CyclicBarrier barrier = new CyclicBarrier(threadNum, new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " 完成最后任务");
}
});
for(int i = 0; i < threadNum; i++) {
new TaskThread(barrier).start();
}
}
}
打印结果
Thread-1 到达栅栏 A
Thread-3 到达栅栏 A
Thread-0 到达栅栏 A
Thread-4 到达栅栏 A
Thread-2 到达栅栏 A
Thread-2 完成最后任务
Thread-2 冲破栅栏 A
Thread-1 冲破栅栏 A
Thread-3 冲破栅栏 A
Thread-4 冲破栅栏 A
Thread-0 冲破栅栏 A
Thread-4 到达栅栏 B
Thread-0 到达栅栏 B
Thread-3 到达栅栏 B
Thread-2 到达栅栏 B
Thread-1 到达栅栏 B
Thread-1 完成最后任务
Thread-1 冲破栅栏 B
Thread-0 冲破栅栏 B
Thread-4 冲破栅栏 B
Thread-2 冲破栅栏 B
Thread-3 冲破栅栏 B
CyclicBarrier实现原理
允许一组线程全部等待彼此达到共同屏障点的同步辅助。 循环阻塞在涉及固定大小的线程方的程序中很有用,这些线程必须偶尔等待彼此。 屏障被称为循环 ,因为它可以在等待的线程被释放之后重新使用。
A CyclicBarrier支持一个可选的Runnable命令,每个屏障点运行一次,在派对中的最后一个线程到达之后,但在任何线程释放之前。 在任何一方继续进行之前,此屏障操作对更新共享状态很有用。
实现原理:在CyclicBarrier的内部定义了一个Lock对象,每当一个线程调用await方法时,将拦截的线程数减1,然后判断剩余拦截数是否为初始值parties,如果不是,进入Lock对象的条件队列等待。如果是,执行barrierAction对象的Runnable方法,然后将锁的条件队列中的所有线程放入锁等待队列中,这些线程会依次的获取锁、释放锁。
构造方法
CyclicBarrier(int parties)
创建一个新的 CyclicBarrier ,当给定数量的线程(线程)等待它时,它将跳闸,并且当屏障跳闸时不执行预定义的动作。
CyclicBarrier(int parties, Runnable barrierAction)
创建一个新的 CyclicBarrier ,当给定数量的线程(线程)等待时,它将跳闸,当屏障跳闸时执行给定的屏障动作,由最后一个进入屏障的线程执行。
方法
int await() 等待所有 parties已经在这个障碍上调用了 await 。
int await(long timeout, TimeUnit unit) 等待所有 parties已经在此屏障上调用 await ,或指定的等待时间过去。
int getNumberWaiting() 返回目前正在等待障碍的各方的数量。
int getParties() 返回旅行这个障碍所需的parties数量。
boolean isBroken() 查询这个障碍是否处于破碎状态。
void reset() 将屏障重置为初始状态。