CountDownLatch
直译过来就是倒计时闩锁,主要用来解决一个线程需要等待指定线数量程完成工作的场景。
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i = 1; i <= 6; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "--被消灭");
countDownLatch.countDown();
}, CountryEnum.provide(i)).start();
}
countDownLatch.await();//必须到达0之后才会开始执行await后面的方法
System.out.println("秦国称霸");
}
}
enum CountryEnum {
ONE(1, "齐"),
TWO(2, "楚"),
THREE(3, "燕"),
FOUR(4, "赵"),
FIVE(5, "韩"),
SIX(6, "魏");
private int num;
private String name;
CountryEnum(int num, String name) {
this.name = name;
this.num = num;
}
public int getNum() {
return num;
}
public String getName() {
return name;
}
public static String provide(int id) {
CountryEnum[] values = CountryEnum.values();//获得所有枚举的方法
for (CountryEnum value : values) {
if (id == value.getNum()) {
return value.getName();
}
}
return "";
}
}
执行结果如下:
齐--被消灭
楚--被消灭
燕--被消灭
赵--被消灭
韩--被消灭
魏--被消灭
秦国称霸
可以看到只要计数到达了0,主线程就会苏醒。调用countDown方法的时候线程并不会阻塞,主线程调用await方法才会阻塞线程。
CyclicBarrier--篱栅
和CountDownLatch相反,让一组线程到达一个同步点时被阻塞,直到最后一个线程到达同步点的时候,所有被同步点拦截的线程才会继续干活,想让线程被同步点控制使用await方法。
public class CyclicBarrierDemo {
public static void main(String[] args) {
//第一个参数规定触发条件所需要的线程数,第二个参数是一个Runnable接口
CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> {
System.out.println("召唤神龙");
});
for (int i = 0; i <7; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName()+"--收集龙珠");
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}, "" + i).start();
}
}
}
结果
0--收集龙珠
5--收集龙珠
2--收集龙珠
6--收集龙珠
1--收集龙珠
3--收集龙珠
4--收集龙珠
召唤神龙
Semaphore--信号量
类似于饭店吃饭,座位是固定的,如果客人想用餐就需要等待其他人用餐完毕空出一个位置。Semaphore主要用于多个共享资源的互斥使用,另一个主要用于并发线程数的控制。
public class SemaphoreDemo {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(3);//模拟饭店有三个空位
for (int i = 0; i <6; i++) {//模拟客人用餐
new Thread(() -> {
try {
semaphore.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("乘客"+Thread.currentThread().getName()+"正在用餐");
try{ TimeUnit.SECONDS.sleep(2); }catch (InterruptedException e){ e.printStackTrace(); }
System.out.println("乘客"+Thread.currentThread().getName()+"用餐完毕");
semaphore.release();
}, "" + i).start();
}
}
}
运行结果:
乘客0正在用餐
乘客4正在用餐
乘客1正在用餐
乘客4用餐完毕
乘客1用餐完毕
乘客0用餐完毕
乘客3正在用餐
乘客2正在用餐
乘客5正在用餐
乘客5用餐完毕
乘客3用餐完毕
乘客2用餐完毕