闭锁

闭锁是一种同步工具类,可以延迟线程的进度知道其到达终止状态。

闭锁的作用相当于一扇门:在闭锁到达结束状态前,这扇门一直是关闭的,并且没有任何线程可以通过,当到达结束状态时,这扇门会打开并允许所有的线程通过。

当闭锁到达结束状态后,将不会再改变状态,因此这扇门将永远保持打开状态。

闭锁可以用来确保某些活动直到其他活动都完成后才继续执行。例如

  • 确保某个计算在其需要的所有资源都初始化之后才继续执行。

  • 确保某个服务在其依赖的所有其他服务都已经启动之后才气动。

  • 等待直到某个操作的所有参与者都就绪再继续执行。

CountDownLatch类

CountDownLatch类是一种灵活的闭锁实现,可以在上述各种情况中使用,他可以使一个或多个线程等待一组事件发生。

CountDownLatch类包括一个计数器,该计数器初始化为一个正数,表示需要等待的事件数量。countDown方法递减计数器,表示有一个时间已经发生了,而await方法会暂停线程一直到计数器到达0。计数器到达0,表示所有需要等待的事件都已经发生,此时会打开线程大门,放出所有被阻塞的线程。

public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {
        //阻塞main线程的“大门”,需要有另外10个线程都准备好,才会解开
        CountDownLatch mainGate = new CountDownLatch(10);

        //阻塞其他线程的“大门”,需要main线程打开
        CountDownLatch otherGate = new CountDownLatch(1);


        //创建10个线程
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                try {
                    //该线程准备好后,将mainGate的值减1,当10个线程都准备好后,mainGate自然被置为0
                    mainGate.countDown();
                    //使用otherGate阻塞当前线程,知道otherGate的值被置为0
                    otherGate.await();

                    long startTime = System.currentTimeMillis();
                    int num = 0;
                    for (int j = 0; j < 100000; j++) {
                        num += j;
                    }
                    long endTime = System.currentTimeMillis();

                    System.out.println(Thread.currentThread() + ":使用了" + (endTime - startTime) + "毫秒");

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }

        //main线程在此阻塞,直到10个线程都准备好
        mainGate.await();

        //打开其他线程的大门
        otherGate.countDown();

    }
}