线程计数器 CountDownLatch
CountDownLatch:它允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行
public class SummonDragonDemo {
private static final int THREAD_COUNT_NUM = 7;
private static CountDownLatch countDownLatch = new CountDownLatch(THREAD_COUNT_NUM);
public static void main(String[] args) throws InterruptedException {
for (int i = 1; i <= THREAD_COUNT_NUM; i++) {
int index = i;
new Thread(() -> {
try {
System.out.println("第" + index + "颗龙珠已收集到!");
//模拟收集第i个龙珠,随机模拟不同的寻找时间
Thread.sleep(new Random().nextInt(3000));
} catch (InterruptedException e) {
e.printStackTrace();
}
//每收集到一颗龙珠,需要等待的颗数减1
countDownLatch.countDown();
}).start();
}
//等待检查,即上述7个线程执行完毕之后,执行await后边的代码
countDownLatch.await();
System.out.println("集齐七颗龙珠!召唤神龙!");
}
}
countDownLatch.await()会等待7个线程都走完,才执行下面的操作。
循环屏障 CyclicBarrier
public class SummonDragonDemo {
private static final int THREAD_COUNT_NUM = 7;
public static void main(String[] args) {
//设置第一个屏障点,等待召集齐7位法师
CyclicBarrier callMasterBarrier = new CyclicBarrier(THREAD_COUNT_NUM, new Runnable() {
@Override
public void run() {
System.out.println("7个法师召集完毕,同时出发,去往不同地方寻找龙珠!");
summonDragon();
}
});
//召集齐7位法师
for (int i = 1; i <= THREAD_COUNT_NUM; i++) {
int index = i;
new Thread(() -> {
try {
System.out.println("召集第" + index + "个法师");
callMasterBarrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
}
/**
* 召唤神龙:1、收集龙珠;2、召唤神龙
*/
private static void summonDragon() {
//设置第二个屏障点,等待7位法师收集完7颗龙珠,召唤神龙
CyclicBarrier summonDragonBarrier = new CyclicBarrier(THREAD_COUNT_NUM, new Runnable() {
@Override
public void run() {
System.out.println("集齐七颗龙珠!召唤神龙!");
}
});
//收集7颗龙珠
for (int i = 1; i <= THREAD_COUNT_NUM; i++) {
int index = i;
new Thread(() -> {
try {
System.out.println("第" + index + "颗龙珠已收集到!");
summonDragonBarrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
}
}
callMasterBarrier.await()和 summonDragonBarrier.await();会等待7个线程都到屏障后才执行下面的操作
区别
- CountDownLatch 的计数器只能使用一次。而 CyclicBarrier 的计数器可以使用 reset() 方法重置
- CountDownLatch 会阻塞主线程,CyclicBarrier 不会阻塞主线程,只会阻塞子线程