闭锁CountDownLatch和栅栏CyclicBarrier之异同举例

本文探讨了CountDownLatch和CyclicBarrier这两种并发工具的区别与联系,并通过两个实例展示了它们在实际应用中的不同之处。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CountDownLatch和CyclicBarrier的主要联系和区别如下:
1.闭锁CountDownLatch做减计数,而栅栏CyclicBarrier则是加计数。
2.CountDownLatch是一次性的,CyclicBarrier可以重用。
3.CountDownLatch强调一个线程等多个线程完成某件事情。CyclicBarrier是多个线程互等,等大家都完成。
4.鉴于上面的描述,CyclicBarrier在一些场景中可以替代CountDownLatch实现类似的功能。

另外,值得一提的是,CountDownLatch和CyclicBarrier在创建和启动线程时,都没有明确提到同时启动全部线程,事实上这在技术上是不大可能,不必要,不提倡的。

先看例子一:
[code]
class SubRunnable implements Runnable {
private CountDownLatch begin, end;
private List<Integer> sublist;

public SubRunnable(List<Integer> sublist, CountDownLatch begin,CountDownLatch end) {
this.sublist = sublist;

this.begin = begin;
this.end = end;
}

@Override
public void run() {
try {
begin.await();

if (sublist != null) {
for (int i : sublist) {
System.out.println("线程" + Thread.currentThread().getName() + ", i = " + i);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally{
System.out.println(System.currentTimeMillis() + ",线程" + Thread.currentThread().getName() + ",开始执行!");
end.countDown();
}
}
}

public class BatchWithCountDownLatch {
private static final int MAX = 3;

private static void list(List<Integer> list) {
if(list == null){
list = new ArrayList<Integer>();
}

for(int i = 0 ;i < 1000;i++){
list.add(i);
}
}

public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
list(list);

//把list拆分成多个
int mod = list.size() % MAX;
int threadCount = mod == 0 ? list.size() / MAX : list.size() / MAX + 1;
ExecutorService executors = Executors.newFixedThreadPool(threadCount);

CountDownLatch begin = new CountDownLatch(1);
CountDownLatch end = new CountDownLatch(threadCount);

for(int i = 0; i< threadCount;i++){
int subsize = (i + 1) * MAX;
executors.execute(new SubRunnable(list.subList(i * MAX, subsize > list.size() ? list.size() : subsize),begin,end));
}

System.out.println("开始 !");
begin.countDown();
long startTime = System.currentTimeMillis();

try {
end.await();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("线程" + Thread.currentThread().getName() + "," + System.currentTimeMillis() + ", 所有线程已完成,开始进入下一步!");
System.out.println("花费时间 -> " + (System.currentTimeMillis() - startTime) + " ms");
}

System.out.println("开始进入第二步操作! ");

System.out.println("end! ");
}
}
[/code]
这是根据jdk文档中的伪代码例程,编写的一个例子,我们完全可以将这个例程改为只使用一个CountDownLatch来实现之。经过测试,发现begin的引入对程序基本无用,当list是1000的数量级时,最先启动的线程仍然比最后启动的快几十毫秒左右;而不设置begin开始闭锁的程序,也是完全一样的情况。

例子二:
[code]
class SubRunnable implements Runnable {
private CyclicBarrier cyclicBarrier;
private List<Integer> sublist;

public SubRunnable(List<Integer> sublist, CyclicBarrier cyclicBarrier) {
this.sublist = sublist;
this.cyclicBarrier = cyclicBarrier;
}

@Override
public void run() {
try {
System.out.println(System.currentTimeMillis() + ",线程" + Thread.currentThread().getName() + ",开始执行!");
if(sublist != null){
for(int i : sublist){
System.out.println("线程" + Thread.currentThread().getName() + ", i = " + i);
}
}

cyclicBarrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
}

public class ReplaceCountDownLatch {
private static final int MAX = 3;

private static void list(List<Integer> list) {
if(list == null){
list = new ArrayList<Integer>();
}

for(int i = 0 ;i < 10;i++){
list.add(i);
}
}

public static void main(String[] args) throws InterruptedException, BrokenBarrierException {
List<Integer> list = new ArrayList<Integer>();
list(list);

//把list拆分成多个
int mod = list.size() % MAX;
int threadCount = mod == 0 ? list.size() / MAX : list.size() / MAX + 1;
ExecutorService executors = Executors.newFixedThreadPool(threadCount);

final CyclicBarrier cyclicBarrier = new CyclicBarrier(threadCount,new Runnable() {
@Override
public void run() {
//根据jdkdoc里的描述,哪个线程最后运行完,就执行下面的代码。
System.out.println("线程" + Thread.currentThread().getName() + "," + System.currentTimeMillis() + ", 所有线程已完成,开始进入下一步!");
}
});

for(int i = 0; i< threadCount;i++){
int subsize = (i + 1) * MAX;
executors.execute(new SubRunnable(list.subList(i * MAX, subsize > list.size() ? list.size() : subsize),cyclicBarrier));
}

cyclicBarrier.await();
executors.shutdown();
System.out.println("开始进入第二步操作! ");


System.out.println("end! ");
}
}
[/code]
使用栅栏CyclicBarrier实现和上面闭锁CountDownLatch相同的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值