少计数 CountDownLatch
CountDownLatch 类可以设置一个计数器,然后通过 countDown 方法来进行减 1 的操作,使用 await 方法等待计数器不大于 0,然后继续执行 await 方法之后的语句。
-
CountDownLatch 主要有两个方法,当一个或多个线程调用 await 方法时,这些线程会阻塞
-
其它线程调用 countDown 方法会将计数器减 1(调用 countDown 方法的线程不会阻塞)
-
当计数器的值变为 0 时,因 await 方法阻塞的线程会被唤醒,继续执行
案例
//7位同学都离开教室,班长锁门
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i = 1; i <= countDownLatch.getCount(); i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()+" 号同学离开教室");
countDownLatch.countDown(); //计数器减1
}).start();
}
countDownLatch.await(); //计数器不为0的时候继续等待
System.out.println(Thread.currentThread().getName()+" 班长锁门");
}
}
循环栅栏 CyclicBarrier
允许一组线程全部等待彼此达到共同屏障点的同步辅助。 循环阻塞在涉及固定大小的线程方的程序中很有用,这些线程必须偶尔等待彼此。 屏障被称为循环 ,因为它可以在等待的线程被释放之后重新使用。
举个例子,就像生活中我们会约朋友们到某个餐厅一起吃饭,有些朋友可能会早到,有些朋友可能会晚到,但是这个餐厅规定必须等到所有人到齐之后才会让我们进去。这里的朋友们就是各个线程,餐厅就是 CyclicBarrier。
CyclicBarrier 的构造方法第一个参数是目标障碍数,每次执行 CyclicBarrier 一次障碍数会加一,如果达到了目标障碍数,才会执行 cyclicBarrier.await()之后的语句。可以将 CyclicBarrier 理解为加 1 操作
案例
//集齐7颗龙珠召唤神龙
public class CyclicBarrierDemo {
//创建固定值
private static final int NUMBER = 7;
public static void main(String[] args) {
//创建CyclicBarrier
CyclicBarrier cyclicBarrier = new CyclicBarrier(NUMBER,()->{
System.out.println("***集齐7颗龙珠召唤神龙***");
});
//集齐7颗龙珠
for (int i = 1; i <=7 ; i++) {
new Thread(()->{
try {
System.out.println(Thread.currentThread().getName()+" 星龙珠");
cyclicBarrier.await();
} catch (Exception e) {
e.printStackTrace();
}
},String.valueOf(i)).start();
}
}
}
信号量机制 Semaphore
Semaphore 的构造方法中传入的第一个参数是最大信号量(可以看成最大线程池),每个信号量初始化为一个最多只能分发一个许可证。使用 acquire 方法获得许可证,release 方法释放许可
//6辆汽车,3个停车位
public class SemaphoreDemo {
public static void main(String[] args) {
//创建semaphore
Semaphore semaphore = new Semaphore(3);
//模拟6辆汽车
for (int i = 1; i <=6 ; i++) {
new Thread(()->{
try {
semaphore.acquire();
System.out.println("第"+Thread.currentThread().getName()+" 汽车抢得车位");
TimeUnit.SECONDS.sleep(5);//设置5秒离开车位
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
semaphore.release();
System.out.println("====第"+Thread.currentThread().getName()+"离开了车位====");
}
},String.valueOf(i)).start();
}
}
}