CountDownLatch

  • 原理:初始化时需要设置一个count变量,await()方法会阻塞当前线程,当其他线程调用CountDownLatch的countDown()方法的次数等于count时,当前线程被唤醒。
  • 适用场景:可用于等待多个线程完成操作之后,当前线程继续操作的场景。
public static void main(String[] args) {
    CountDownLatch countDownLatch = new CountDownLatch(3);
    for (int i = 0 ; i < 3 ; i++) {
        int count = i;
        new Thread(() -> {
            System.out.println("Count down thread id : " + count);
            countDownLatch.countDown();
        }).start();
    }
    try {
        System.out.println("Main thread await!");
        countDownLatch.await();
        System.out.println("Main thread finish!");
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

从日志输出可以看到,主线程进入等待,当所有子线程均调用了countDown后,主线程继续执行:

Main thread await!
Count down thread id : 1
Count down thread id : 0
Count down thread id : 2
Main thread finish!

CyclicBarrier

  • 原理:CyclicBarrier是一道屏障,调用await方法后,当前线程进入阻塞,当parties数量的线程调用await方法后,所有的await方法会返回并继续往下执行。
  • 适用场景:可用于需要多个线程均到达某一步之后才能继续往下执行的场景
public static void main(String[] args) {
    CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
    for (int i = 0; i < 3; i++) {
        int count = i;
        new Thread(() -> {
            try {
                Thread.sleep(3L);
                System.out.println("Thread id waiting : " + count);
                cyclicBarrier.await();
                System.out.println("Thread id finish : " + count);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

从日志可以看到,所有线程首先输出waiting,然后再输出finish:

Thread id waiting : 2
Thread id waiting : 0
Thread id waiting : 1
Thread id finish : 1
Thread id finish : 2
Thread id finish : 0

Semaphore

  • 原理:Semaphore就是信号量,允许特定数量的线程同时执行。调用acquire方法获取锁,调用release方法释放锁
  • 适用场景:允许特定数量线程同时执行的场景
public static void main(String[] args) {
    Semaphore semaphore = new Semaphore(3);
    for (int i = 0 ; i < 5 ; i++) {
        int count = i;
        new Thread(() -> {
            try {
                semaphore.acquire();
                System.out.println("Thread got semaphore : " + count);
                Thread.sleep(2L);
                semaphore.release();
                System.out.println("Thread release semaphore : " + count);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

从日志中可以看出,0、1、2共3个线程首先获取了锁,随后1首先释放锁,释放后3获取了锁,获取锁的总线程仍为3。随后0释放了锁,此时4就可以获取锁,执行的总线程仍为3。

Thread got semaphore : 0
Thread got semaphore : 1
Thread got semaphore : 2
Thread release semaphore : 1
Thread got semaphore : 3
Thread release semaphore : 0
Thread got semaphore : 4
Thread release semaphore : 2
Thread release semaphore : 4
Thread release semaphore : 3

magicTan
15 声望0 粉丝