concurrent包里的CountDownLatch

CountDownLatch是一个非常实用的多线程控制工具类

CountDownLatch是通过一个计数器来实现的,计数器的初始值是线程的数量.每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了

常用方法

//构造方法,创建一个值为count 的计数器。
public CountDownLatch(int count) {  }; 
​//阻塞当前线程,将当前线程加入阻塞队列。
public void await() throws InterruptedException { };  
​//在timeout的时间之内阻塞当前线程,时间一过则当前线程可以执行,
public boolean await(long timeout, TimeUnit unit) throws InterruptedException { }; 
​//对计数器进行递减1操作,当计数器递减至0时,当前线程会去唤醒阻塞队列里的所有线程。
public void countDown() { }; 

eg:

(1)计数器为2,有2个子线程来完成子任务,主线程等待5子线程执行完才继续执行

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CountDownLatchDemo{

    private static CountDownLatch cdl = new CountDownLatch(2);
    public static void main(String[] args) throws InterruptedException {
        System.out.println("主线程开始执行…");
        //第一个子线程执行
        ExecutorService es1 = Executors.newSingleThreadExecutor();
        es1.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                    System.out.println("子线程:"+Thread.currentThread().getName()+"执行");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                cdl.countDown();
            }
        });
        es1.shutdown();

        //第二个子线程执行
        ExecutorService es2 = Executors.newSingleThreadExecutor();
        es2.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("子线程:"+Thread.currentThread().getName()+"执行");
                cdl.countDown();
            }
        });
        es2.shutdown();
        System.out.println("等待两个线程执行完毕…");
        try {
            cdl.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("两个子线程都执行完毕,继续执行主线程");
    }
}

输出

主线程开始执行
等待两个线程执行完毕
子线程:pool-1-thread-1执行
子线程:pool-2-thread-1执行
两个子线程都执行完毕,继续执行主线程

(2)计数器为5,有5个线程来完成任务,主线程等待5线程执行完才继续执行

import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CountDownLatchDemo implements Runnable{

    private static CountDownLatch cdl = new CountDownLatch(5);
    private static CountDownLatchDemo demo = new CountDownLatchDemo();
    @Override
    public void run() {
        try {
            Thread.sleep(new Random().nextInt(10) * 1000);
            System.out.println(Thread.currentThread().getName()+"  check");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //计数减一
            cdl.countDown();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ExecutorService exec = Executors.newFixedThreadPool(5);
        for (int i=0; i<5; i++){
            exec.submit(demo);
        }
        // 等待
        cdl.await();
        System.out.println("end!");
        // 关闭线程池
        exec.shutdown();

    }
}

输出:

pool-1-thread-1 check
pool-1-thread-3 check
pool-1-thread-2 check
pool-1-thread-5 check
pool-1-thread-4 check
end!

 
 
posted @ 2020-04-01 14:24  慕尘  阅读(206)  评论(0编辑  收藏  举报