线程的并发工具类(2)—CountDownLatch

  • Post author:
  • Post category:其他

1、CountDownLatch介绍

CountDownLatch,线程的同步工具类。
作用:是一组线程等待其他的线程完成工作以后在执行,加强版join。由外部因素(线程)去控制。

1.1、用法场景

1、某一线程在开始运行前等待n个线程执行完毕。启动一个服务时,主线程需要等待多个组件加载完毕,之后再继续执行。(多个准备线程,一个工作线程)

2、实现多个线程开始执行任务的最大并行性。注意是并行性,不是并发,强调的是多个线程在某一时刻同时开始执行。类似于赛跑,将多个线程放到起点,等待发令枪响,然后同时开跑。(一个准备线程,多个工作线程)

1.2、原理

在初始化CountDownLatch实例的时候,会同时将计数器的值进行初始化new CountDownLatch(5)。工作线程调用await()方法进行等待,而当准备工作调用countDown()时,计数器就会减1,当计数器的值变为0时,调用await()方法的线程就会继续向下执行。
和join()方法比较类似,类似的任务可以使用线程的 join() 方法实现:在等待时间点调用其他线程的 join() 方法,当前线程就会等待join线程执行完之后才继续执行,但 CountDownLatch 实现更加简单,并且比 join 的功能更多。

2、CountDownLatch实例

CountDownLatch中主要有两个方法配合来实现了它的功能:countDown()和await(),作用不再赘述。

package com.ld.task;

import java.util.concurrent.CountDownLatch;

public class UseCountDownLatch implements Runnable {
    //创建CountDownLatch实例,初始化计数器的值
    static CountDownLatch countDownLatch = new CountDownLatch(6);

    @Override
    public void run() {
        System.out.println("Thread " + Thread.currentThread().getName() + " 开始准备工作...");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Thread " + Thread.currentThread().getName() + " 准备工作完成...");
        countDownLatch.countDown();
    }

    static class WorkTask implements Runnable {
        @Override
        public void run() {
            try {
                System.out.println("工作线程等待准备工作的线程执行完成...");
                countDownLatch.await();//等待计数器的值变为0,继续向下执行
                System.out.println("工作线程 Thread" + Thread.currentThread().getName() + "开始工作...");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        System.out.println("main线程开始工作...");
        new Thread(new WorkTask()).start();
        for (int i = 0; i < 4; i++) {
            new Thread(new UseCountDownLatch()).start();
        }
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println(Thread.currentThread().getName() + "线程准备工作第一步...");
                    Thread.sleep(1000);
                    countDownLatch.countDown();
                    System.out.println(Thread.currentThread().getName() + "线程准备工作第二步...");
                    Thread.sleep(1000);
                    countDownLatch.countDown();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

上面实例中CountDownLatch 计数器初始值设置为6,首先调用工作线程等待,然后循环调用了准备工作线程4次,最后又调用另外一个准备线程将计数器的值减掉两次。
运行结果:

main线程开始工作...
工作线程等待准备工作的线程执行完成...
Thread Thread-1 开始准备工作...
Thread Thread-4 开始准备工作...
Thread Thread-2 开始准备工作...
Thread-5线程准备工作第一步...
Thread Thread-3 开始准备工作...
Thread-5线程准备工作第二步...
Thread Thread-4 准备工作完成...
Thread Thread-1 准备工作完成...
Thread Thread-2 准备工作完成...
Thread Thread-3 准备工作完成...
工作线程 ThreadThread-0开始工作...

版权声明:本文为qq_19674263原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。