一、CountDownLatch--减少计数
CountDownLatch类可以设置一个计数器,然后通过countDown
方法来进行减1的操作
,使用await
方法等待计数器不大于0
,然后继续执行await方法之后的语句。
CountDownLatch主要有两个方法,当一个或多个线程调用await方法时,这些线程会阻塞。
其它线程调用countDown方法会将计数器减1(调用countDown方法的线程不会阻塞) 。
当计数器的值变为0时,因await方法阻塞的线程会被唤醒,继续执行。
使用场景:6个同学陆续离开教室后值班同学才可以关门
public class CountDownLatchDemo{
public static void main(String[] args) throws InterruptedException {
CountDownLatch cdl = new CountDownLatch(6);
System.out.println("主线程休眠了");
for (int i = 1; i <= 6; i++) {
new Thread(()->{
if (Thread.currentThread().getName().equals("线程6")){
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "离开了");
cdl.countDown();
},"线程" + i).start();
}
cdl.await();
System.out.println("全部离开了,现在计数器为" + cdl.getCount());
}
}
二、CyclicBarrier--循环栅栏
CyclicBarrier的构造方法第一个参数是目标障碍数,每次执行CyclicBarrier一次障碍数会加一,如果达到了目标障碍数,才会执行cyclicBarrier.await()之后的语句。可以将CyclicBarrier理解为加1操作。
使用场景:集齐7颗龙珠就可以召唤神龙
public class CyclicBarrierDemo{
private static final int NUM = 7;
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(NUM,()->{
System.out.println("收集" + NUM + "完成,召唤神龙许愿");
});
for (int i = 1; i <= 7; i++) {
new Thread(()->{
System.out.println("争抢" + Thread.currentThread().getName() + "开始");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("争抢" + Thread.currentThread().getName() + "结束");
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
},"龙珠" + i + "号").start();
}
}
}
三、Semaphore--信号灯
Semaphore的构造方法中传入的第一个参数是最大信号量(可以看成最大线程池),每个信号量初始化为一个最多只能分发一个许可证。使用acquire方法获得许可证,release方法释放许可。
使用场景:抢车位,6辆车3个车位
public class SemaphoreDemo {
public static void main(String[] args) throws InterruptedException {
Semaphore semaphore = new Semaphore(3);
for (int i = 1; i <= 6; i++) {
Thread.sleep(1000);
//停车
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() + "找车位ing");
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + "汽车停车成功!");
Thread.sleep(10000);
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName() + "溜了溜了");
semaphore.release();
}
}, "汽车" + i).start();
}
}
}