• CountnDownLatch表示计数器,可以在构造方法中传入初始化的计数值,当一个线程调用它的await()方法将会阻塞,其他线程调用countDown()方法,对CountDownLatch中的数字减少一,当数字为0是,所有被阻塞的线程都将被唤醒。

    • 底层实现的原理就是调用await()方法的时候会利用AQS进行排队,一旦数字为0,将会从AQS中排队的线程依次唤醒

    • public static void main(String[] args) {
              CountDownLatch countDownLatch = new CountDownLatch(6);
      
              for (int i = 0; i < 6; i++) {
                  new Thread(() -> {
                      try {
                          Random random = new Random();
                          // 模拟业务执行时间
                          Thread.sleep(random.nextInt(6000));
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                      System.out.println("当前线程:"+Thread.currentThread().getName());
                      countDownLatch.countDown();
                  }).start();
              }
      
              try {
                  countDownLatch.await();
                  System.out.println("终于轮到我执行了");
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
          }
      
  • Semaphore表示信号量,表示同时允许最多多少个线程使用该信号量,通过acquire()方法来获取许可,如果没有许可可用则线程阻塞,并通过AQS来排队,通过release()方法来释放许可,当某个线程释放许可的时候,会从AQS中排队的线程依次唤醒

    • public static void main(String[] args) {
              // 一共只有一个车位
              Semaphore semaphore = new Semaphore(1);
      
              for (int i = 0; i < 3; i++) {
                  new Thread(() -> {
                      try {
                          semaphore.acquire();
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                      System.out.println("当前线程抢到车位:"+Thread.currentThread().getName());
                      Random random = new Random();
                      try {
                          Thread.sleep(random.nextInt(6000));
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                      semaphore.release();
                      System.out.println("当前线程离开车位:"+Thread.currentThread().getName());
      
                  }).start();
              }
          }
      
  • CyclicBarrier表示线程屏障,让一组线程到达一个屏障点的时候进行阻塞,直到最后一个线程到达屏障点,屏障barrier才会释放,线程进入屏障使用await()方法

    • public static void main(String[] args) {
              CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> System.out.println("终于等到我执行了"));
              for (int i = 0; i < 7; i++) {
                  new Thread(() -> {
                      Random random = new Random();
                      try {
                          Thread.sleep(random.nextInt(6000));
                          System.out.println("当前任务执行完成:" + Thread.currentThread().getName());
                          try {
                              cyclicBarrier.await();
                          } catch (BrokenBarrierException e) {
                              e.printStackTrace();
                          }
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
      
                  }).start();
              }
          }
      

Q.E.D.