CountDownLatch和CyclicBarrier的简单使用

转自:http://www.kissyu.org/2016/07/18/%E5%AD%A6%E4%B9%A0%E4%BD%BF%E7%94%A8CountDownLatch%E5%92%8CCyclicBarrier/

简介

CountDownLatch和CyclicBarrier都是线程同步的辅助工具。

CountDownLatch

CountDownLatch可以想象成一个上了N把锁的门栓。当某个线程调用await方法时,它会去检测当前门栓上是否有锁,如果有锁的话就继续执行,否则就继续等待,知道全部的锁都被解除。可以通过调用countDown方法来从门栓上解除一把锁。

有一个十分典型的应用场景就是利用CountDownLatch来保证线程同时开始执行或者保证当前线程等待其他线程全部结束之后继续执行,代码如下:

     
     
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
     
     
public class TestDemo {
public static void main(String args[]) throws InterruptedException {
int threadCount = 10;
CountDownLatch startSignal = new CountDownLatch( 1);
CountDownLatch doneSignal = new CountDownLatch(threadCount);
for ( int i = 0; i < threadCount; i++) {
// create and start threads
new Thread( new Worker(startSignal, doneSignal, "th-" + i)).start();
}
System.out.println( "sub threads waiting for main thread");
startSignal.countDown(); // let all threads proceed
doneSignal.await(); // wait for all to finish
System.out.println( "sub threads complete");
}
static class Worker implements Runnable {
private final CountDownLatch startSignal;
private final CountDownLatch doneSignal;
private final String name;
Worker(CountDownLatch startSignal, CountDownLatch doneSignal, String name) {
this.startSignal = startSignal;
this.doneSignal = doneSignal;
this.name = name;
}
public void run() {
try {
startSignal.await();
doWork();
doneSignal.countDown();
}
catch (InterruptedException ex) {
} // return;
}
void doWork() {
System.out.println( this.name + " is doing work");
}
}
}

执行结果如下:

     
     
1
2
3
4
5
6
7
8
9
10
11
12
     
     
sub threads waiting for main thread
th-0 is doing work
th-3 is doing work
th-4 is doing work
th-1 is doing work
th-2 is doing work
th-9 is doing work
th-8 is doing work
th-7 is doing work
th-5 is doing work
th-6 is doing work
sub threads complete

CyclicBarrier

我们可以用学校春游之前在操场集合的这个场景来理解CyclicBarrier。一个班级如果要出发,那么必须要等班里所有的人都到了才能走。到了集合地点的人需要签到,然后等待其他人,这个过程就像CyclicBarrier中的await方法。当所有人都签到完毕,班主任会上前说一些注意事项,这一步就像下面代码中的barrierAction。然后,所有人才可以出发,在代码中的表现就是继续执行await之后的方法。示例代码如下:

     
     
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
     
     
public class TestDemo {
public static void main(String args[]) throws InterruptedException {
int threadCount = 10;
Runnable barrierAction = new Runnable() {
public void run() {
System.out.println( "sub threads complete");
}
};
CyclicBarrier barrier = new CyclicBarrier(threadCount, barrierAction);
List<Thread> threads = new ArrayList<>(threadCount);
for ( int i = 0; i < threadCount; i++) {
Thread thread = new Thread( new Worker(barrier, "th-" + i));
threads.add(thread);
thread.start();
}
// wait until done
for (Thread thread : threads) {
thread.join();
}
}
public static class Worker implements Runnable {
private CyclicBarrier barrier;
private String name;
Worker(CyclicBarrier barrier, String name) {
this.barrier = barrier;
this.name = name;
}
public void run() {
try {
doWork();
barrier.await();
System.out.println(name + " waiting finish");
}
catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
private void doWork() {
System.out.println(name + " is doing work");
}
}
}

执行结果如下:

     
     
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
     
     
th-0 is doing work
th-1 is doing work
th-2 is doing work
th-3 is doing work
th-4 is doing work
th-5 is doing work
th-6 is doing work
th-7 is doing work
th-8 is doing work
th-9 is doing work
sub threads complete
th-9 waiting finish
th-0 waiting finish
th-1 waiting finish
th-2 waiting finish
th-4 waiting finish
th-3 waiting finish
th-5 waiting finish
th-7 waiting finish
th-6 waiting finish
th-8 waiting finish

区别

这两个类,在定义上的区别似乎不大。一个是latch,一个是barrier,都体现了阻塞的意思,并且调用await的时候都会阻塞。但是他们阻塞时的线程的关系是不一样的。对于CountDownLatch来说,是一个或多个线程在等待一个或多个线程,他们的等待关系从宏观的角度来看只有一组。而对于CyclicBarrier来说,是所有的线程在互相等待,他们的等待关系是交叉的。

另外一个区别是,CyclicBarrier的barrier是可以复用的(调用reset方法),但是CountDownLatch的latch只能用一次。这个区别在实际的业务当中会产生一定的影响。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值