【JUC】CountDownLatch

Latch:门闩。一种线程通信的方式;当程序不涉及同步,仅仅需要线程通信的时候,使用synchronize或者lock的线程通信等待唤醒机制,就显得太重了;

这时候,可以考虑使用信号量类:CountDownLatch,cylicbarrier,semaphore

CountDownLatch是一个多线程控制工具类。可以实现计数器的功能。

CountDownLatch的两种应用场景:(不能实现多个线程顺序执行!)

1. 让某线程等待其他线程执行完毕,再开始执行;

2. 让多个线程同时开始并行执行;

构造器:

// 传入一个count,指定要等待的线程个数
public CountDownLatch(int count)

主要方法:

// 调用await的线程会被挂起,直到count==0,才会继续执行。
public void await(){};

// 等待一定时间,count还没有为0,线程继续执行
public boolean await(long timeout, TimeUnit unit){};

// 将count值减1,一般在线程执行结束,调用此方法,代表计数器减1.
public void countDown() {};

第一种场景:

让某线程,等待n个线程执行结束,再继续执行;

创建一个Task类

public class Task implements Runnable {
    private String name;
    private CountDownLatch latch;
    // 线程需要CountDownLatch对象
    public Task(CountDownLatch latch, String name) {
        this.latch = latch;
        this.name = name;
    }
    @Override
    public void run() {
        try {
            Thread.sleep(1000);
            System.out.println(this.name + " Over");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            latch.countDown(); // 执行完毕,计数器减一
        }
    }
}

 

主方法:

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CountDownLatchTest {
    public static void main(String[] args) throws InterruptedException {

        CountDownLatch latch = new CountDownLatch(3);
        Task task_A = new Task(latch, "A");
        Task task_B = new Task(latch, "B");
        Task task_C = new Task(latch, "C");
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.submit(task_A);
        executorService.submit(task_B);
        executorService.submit(task_C);
        executorService.shutdown();
        // 挂起mian线程,等待计数器置0,也就是三个线程执行完毕。
        latch.await();
        System.out.println(Thread.currentThread().getName());
    }
}

运行结果:

A Over
B Over
C Over
main    // 等待三个线程执行完毕,main线程执行

第二种场景:

其实跟第一种,基本一样,只不过反着来;await所有的用户线程,让main线程先行,计数器减一,为0;接着用户线程就会一起启动;

这个方式,对于并发其实没有什么用,主要用于并行的场景;真正的同时启动多个线程。

 

posted @ 2019-10-12 14:32  mussessein  阅读(108)  评论(0编辑  收藏  举报