1、CountDownLatch是什么?
CountDownLatch从jdk1.5之后引入在java.util.concurrent包下,CountDownLatch这个类能够使一个线程等待其他线程完成各自的工作后再执行。
2、CountDownLatch如何工作?
CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。
import java.util.concurrent.CountDownLatch; public class Sample { /** * 计数器,用来控制线程 * 传入参数2,表示计数器计数为2 */ private final static CountDownLatch mCountDownLatch = new CountDownLatch(2); /** * 示例工作线程类 */ private static class WorkingThread extends Thread { private final String mThreadName; private final int mSleepTime; public WorkingThread(String name, int sleepTime) { mThreadName = name; mSleepTime = sleepTime; } @Override public void run() { System.out.println("[" + mThreadName + "] started!"); try { Thread.sleep(mSleepTime); } catch (InterruptedException e) { e.printStackTrace(); } mCountDownLatch.countDown(); System.out.println("[" + mThreadName + "] end!"); } } /** * 示例线程类 */ private static class SampleThread extends Thread { @Override public void run() { System.out.println("[SampleThread] started!"); try { // 会阻塞在这里等待 mCountDownLatch 里的count变为0; // 也就是等待另外的WorkingThread调用countDown() mCountDownLatch.await(); } catch (InterruptedException e) { } System.out.println("[SampleThread] end!"); } } public static void main(String[] args) throws Exception { // 最先run SampleThread new SampleThread().start(); // 运行两个工作线程
// 这个例子只能看出SampleThread在WorkingThread之后完成,并不能看出两个WorkingThread之间的顺序 // 工作线程1运行5秒 new WorkingThread("WorkingThread1", 5000).start(); // 工作线程2运行2秒 new WorkingThread("WorkingThread2", 2000).start(); } }
通过上面例子可以知道:
CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。
3、 CountDownLatch 类中主要的方法?
CountDownLatch(int) 默认构造方法
构造器中的计数值(count)实际上就是闭锁需要等待的线程数量。这个值只能被设置一次,而且CountDownLatch没有提供任何机制去重新设置这个计数值。
await() 线程等待其他线程
await(long timeout, TimeUnit unit) 根据时间等待
countDown()
/** *减少锁存器的计数,释放所有等待的线程 *计数达到零。 * 如果当前计数大于零,则它将递减。 *如果新的计数为零,则所有等待的线程都被重新启用 *线程调度的目的。 * * <p>如果当前计数等于零,那么没有任何反应。 */ public void countDown() { sync.releaseShared(1); }
getCount() 返回当前计数