Java的CountDownLatch和CyclicBarrier的理解和区别
CountDown表示减法计数,Latch表示门闩的意思,计数为0的时候就可以打开门闩了。
Cyclic Barrier表示循环的障碍物。
两个类都含有这一个意思:对应的线程都完成工作之后再进行下一步动作,也就是大家都准备好之后再进行下一步。然而两者最大的区别是,进行下一步动作的动作实施者是不一样的。这里的“动作实施者”有两种,一种是主线程(即执行main函数),另一种是执行任务的其他线程,后面叫这种线程为“其他线程”,区分于主线程。
对于CountDownLatch,当计数为0的时候,下一步的动作实施者是main函数;
对于CyclicBarrier,下一步动作实施者是“其他线程”。
CountDownLatch
package com.uwanyi.lottery_draw;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
public class CountDownLatchTest {
public static void main(String[] args) throws InterruptedException {
//如果想要返回结果,则将每个线程放入集合中
List<MyThread> myThreadList = new ArrayList<>();
//英雄联盟5v5 所有玩家都准备就绪后才开始游戏
CountDownLatch latch = new CountDownLatch(5);
for(int i = 0; i < latch.getCount(); i++){
MyThread myThread = new MyThread(latch);
new Thread(myThread, "player"+i).start();
myThreadList.add(myThread);//放入集合
}
System.out.println("正在等待所有玩家准备好");
latch.await();
//获取线程结果
for(MyThread myThread:myThreadList){
//此处可根据需要做其他处理
System.out.println(myThread.getTotal());
}
System.out.println("开始游戏");
}
private static class MyThread implements Runnable{
private CountDownLatch latch ;
private String result;
public MyThread(CountDownLatch latch){
this.latch = latch;
}
@Override
public void run() {
try {
Random rand = new Random();
int randomNum = rand.nextInt((3000 - 1000) + 1) + 1000;//产生1000到3000之间的随机整数
Thread.sleep(randomNum);
System.out.println(Thread.currentThread().getName()+" 已经准备好了, 所使用的时间为 "+((double)randomNum/1000)+"s");
result = Thread.currentThread().getName() + ":" + randomNum;
latch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public String getTotal(){
return result;
}
}
}
CyclicBarrier
package com.uwanyi.lottery_draw;
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierTest {
public static void main(String[] args) {
//5名队友,通过3个关卡。每到一个关卡需要等待5人都到达再进行下一个关卡
CyclicBarrier barrier = new CyclicBarrier(5);
for(int i = 0; i < barrier.getParties(); i++){
new Thread(new MyRunnable(barrier), "队友"+i).start();
}
System.out.println("main function is finished.");
}
private static class MyRunnable implements Runnable{
private CyclicBarrier barrier;
public MyRunnable(CyclicBarrier barrier){
this.barrier = barrier;
}
@Override
public void run() {
//3个关卡
for(int i = 0; i < 3; i++) {
try {
String theadName = Thread.currentThread().getName();
Random rand = new Random();
int randomNum = rand.nextInt((3000 - 1000) + 1) + 1000;//产生1000到3000之间的随机整数
Thread.sleep(randomNum);
System.out.println(theadName + ", 通过了第"+i+"个障碍物, 使用了 "+((double)randomNum/1000)+"s");
//此处是关键,每个线程队友到达此处,会进行等待检查是否已有5名队友到达(包含自己),如果达到规定的5个,则进行下一步
this.barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}
}