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.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 的构造方法中传入的第一个参数是最大信号量(可以看成最大线程池),每个信号量初始化为一个最多只能分发一个许可证。使用 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(); } } }