CountDownLatch

相当于减法计数器
,任务执行完毕就调用countDown()方法,减到0时说明全部执行完毕,
否则会在 await() 阻塞

如果少调用了countDown(),即使任务全部执行完毕也会被一直阻塞。

  1. public static void main(String[] args) throws InterruptedException {
  2. CountDownLatch countDownLatch = new CountDownLatch(6);
  3. for (int i = 0; i < 6; i++) {
  4. new Thread(()->{
  5. System.out.println(Thread.currentThread().getName() + "Done");
  6. countDownLatch.countDown();
  7. }, String.valueOf(i)).start();
  8. }
  9. countDownLatch.await();
  10. System.out.println("全部执行完毕");
  11. }

CyclicBarrier

加法计数器
两种构造方法,
计数次数,到达次数后执行的 Runnable 任务
如果少调用了 await() 也会一直等。

  1. public CyclicBarrier(int parties, Runnable barrierAction) {
  2. if (parties <= 0) throw new IllegalArgumentException();
  3. this.parties = parties;
  4. this.count = parties;
  5. this.barrierCommand = barrierAction;
  6. }
  7. public CyclicBarrier(int parties) {
  8. this(parties, null);
  9. }
  1. public static void main(String[] args) throws InterruptedException {
  2. CyclicBarrier cyclicBarrier = new CyclicBarrier(7, ()->{
  3. System.out.println("全部执行完毕");
  4. });
  5. for (int i = 0; i < 7; i++) {
  6. // 加了 final 会把该变量复制到堆,这样线程才能访问到,否则执行完 for 循环局部变量就没了
  7. // jdk1.8后做了优化,如果不写 final 编译器会给你加上, 但是都不能修改
  8. final int temp = i;
  9. new Thread(()->{
  10. System.out.println(Thread.currentThread().getName() + " " + temp);
  11. try {
  12. cyclicBarrier.await();
  13. } catch (InterruptedException e) {
  14. e.printStackTrace();
  15. } catch (BrokenBarrierException e) {
  16. e.printStackTrace();
  17. }
  18. }).start();
  19. }
  20. }

Semaphore

信号量
同一时间只能有指定的线程数执行。

构造方法参数可以理解为限制的线程数

public Semaphore(int permits) {
    sync = new NonfairSync(permits);
}

下面代码实现同一时间只能有3个线程执行,其他线程只能等待

semaphore.acquire(); 获得执行权,如果没有位置,就等待。
semaphore.release(); 释放,将当前信号量+1,唤醒等待线程。
作用:控制最大线程数

public static void main(String[] args) throws InterruptedException {
    Semaphore semaphore = new Semaphore(3);

    for (int i = 0; i < 6; i++) {
        new Thread(()->{
            try {
                semaphore.acquire();
                System.out.println(Thread.currentThread().getName() + "-抢占");
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                System.out.println(Thread.currentThread().getName() + "-释放");
                semaphore.release();
            }
        }).start();
    }
}