CountDownLatch、CyclicBarrier以及Se
2019-07-24 本文已影响14人
bearPotMan
CountDownLatch
简单讲就是可以实现 “倒计时” 的一个工具类,提供了两个基本的方法,倒计数方法 countDown()
和 阻塞等待方法 await()
。下面通过一个简单的案例来看一下具体该如何使用。
看过香港警匪片的朋友应该很熟悉这样一个场景:假设本次行动警察要抓获 6 个犯罪分子,但是除了第一个犯罪分子,其余犯罪分子的位置都是未知的,得抓一个问一个才能知道,要抓幕后大老板,得把前第5 个犯罪分子抓捕归案才能知道老板的位置,抓了老板才算结案!虽然有点扯,但有助于理解 CountDownLatch 的使用!看代码
public class CountDownLatchDemo {
public static void main(String[] args) {
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i = 0; i < 6; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " 号嫌疑人被抓");
countDownLatch.countDown();
}, String.valueOf(i)).start();
}
try {
countDownLatch.await();
System.out.println("所有嫌疑人被抓捕,结案!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
看结果:
1 号嫌疑人被抓
0 号嫌疑人被抓
4 号嫌疑人被抓
2 号嫌疑人被抓
3 号嫌疑人被抓
5 号嫌疑人被抓
所有嫌疑人被抓捕,结案!
CyclicBarrier
与 CountDownLatch 的作用恰好相反。
来个案例强行解释一波。
想必看过复联3的朋友都知道灭霸吧,灭霸要完成自己的宏图大业,必须要集齐六颗宝石,那么我们就来看一下灭霸是如何集齐六颗宝石,打完响指并毁灭半数人类的。
public class CyclicBarrierDemo {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(6, () -> System.out.println("灭霸响指,毁灭性的时刻"));
for (int i = 1; i <= 6; i++) {
final int temp = i;
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " 收集到了 " + GemEnum.forEach(temp).getDesc());
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}, String.valueOf(i)).start();
}
}
}
enum GemEnum {
SPACE_GEM(1, "空间宝石"),
POWER_GEM(2, "力量宝石"),
TIME_GEM(3, "时间宝石"),
MIND_GEM(4, "心灵宝石"),
SOUL_GEM(5, "灵魂宝石"),
REALISTIC_GEM(6, "现实宝石");
private Integer number;
private String desc;
GemEnum(Integer number, String desc) {
this.number = number;
this.desc = desc;
}
public Integer getNumber() {
return number;
}
public String getDesc() {
return desc;
}
public static GemEnum forEach(int index) {
GemEnum[] gemEnums = GemEnum.values();
for (GemEnum gemEnum : gemEnums) {
if (index == gemEnum.getNumber()) {
return gemEnum;
}
}
return null;
}
}
看下面的结果,完美!
1 收集到了 空间宝石
5 收集到了 灵魂宝石
4 收集到了 心灵宝石
2 收集到了 力量宝石
3 收集到了 时间宝石
6 收集到了 现实宝石
灭霸响指,毁灭性的时刻
Semaphore
信号量通常用于控制线程数!
看这么一个案例:车站只有 3 个售票窗口,每个窗口只能单次服务一位顾客,现在假设有 5 位顾客前来购票,前三位每人一个窗口办理手续,后两位就必须等着前三位办完手续,等窗口空闲了再去办理。看代码
public class SemaphoreDemo {
public static void main(String[] args) {
// 3 个窗口
Semaphore semaphore = new Semaphore(3);
// 5位顾客
for (int i = 1; i <= 5; i++) {
new Thread(() -> {
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + " 号顾客买票");
try {
// 假设每位顾客买票耗时 3 秒
TimeUnit.SECONDS.sleep(3);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 号顾客买完票离开");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();
}
}, String.valueOf(i)).start();
}
}
}
看结果:
3 号顾客买票
1 号顾客买票
2 号顾客买票
2 号顾客买完票离开
1 号顾客买完票离开
3 号顾客买完票离开
4 号顾客买票
5 号顾客买票
5 号顾客买完票离开
4 号顾客买完票离开
以上就是它们三个的简单使用,了解的知识点多了之后,对于不同的场景,你就会有不同的解决方案!加油...