倒计时门闩会导致多天线程在“门口”一直等待,直到另一条线程打开这扇门,线程才得以继续运行。
类CountDownLatch提供一下方法:
void await(): 除非线程被中断,否则强制调用线程一直等到计数器倒数到0。
void countDown(): 递减计数,当计数降至0时,释放所有等待线程。当该方法调用时count已经为0,那么什么也不会发生。
long getCount(): 返回当前的计数。
String toString(): 返回一条标识这个门闩及其状态的字符串。
示例:
package com.thread; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 高级同步器:倒计时门闩 * 倒计时门闩会导致一条或者多条线程在“门口”一直等待(await()),直到另一条(例如主线程)打开这扇门,等待的线程才得以继续运行 * 组成:计数变量和两个操作【1、导致线程等待直到计数变成0(startSignal),2、递减计数变量(doneSignal),确保线程完成工作】 * 注意:递减计数变量不是必须的 * @author Administrator * */ public class CountDownLatchDemo { final static int NTHREADS = 3; public static void main(String[] args) { final CountDownLatch startSignal = new CountDownLatch(1); final CountDownLatch doneSignal = new CountDownLatch(NTHREADS); Runnable r = new Runnable() { @Override public void run() { try { report("entered run()"); startSignal.await(); //进来的线程进入等待,直到count=0 report("doing work"); Thread.sleep((int) (Math.random() * 1000)); //模拟线程各自工作耗时 doneSignal.countDown(); //当前线程计数减1,从3开始递减,确保3个线程都能完成工作 } catch (InterruptedException ie) { System.err.println(ie); } } void report(String s) { System.out.println(System.currentTimeMillis() + ": " + Thread.currentThread() + ": " + s); } }; //创建3个线程的线程池,执行run方法 ExecutorService executor = Executors.newFixedThreadPool(NTHREADS); for (int i = 0; i < NTHREADS; i++) executor.execute(r); try { //主线程等待1秒,确保三个线程都走到await()等待 System.out.println("main thread doing something"); Thread.sleep(1000); //计数器递减,递减到0时释放await上等待的线程,让三个线程同时开始工作 //【startSignal count=1 是因为主线程唤醒线程池里的操作只需要一步,如果存在线程1计算sum1,线程2计算sum2,线程3对sum1和sum2求和,则count=2】 startSignal.countDown(); System.out.println("main thread doing something else"); //等待所有线程执行完毕 doneSignal.await(); //关闭线程池 executor.shutdownNow(); } catch (InterruptedException ie) { System.err.println(ie); } } //main thread doing something //1554712657620: Thread[pool-1-thread-3,5,main]: entered run() //1554712657620: Thread[pool-1-thread-1,5,main]: entered run() //1554712657620: Thread[pool-1-thread-2,5,main]: entered run() //main thread doing something else //1554712658620: Thread[pool-1-thread-1,5,main]: doing work //1554712658621: Thread[pool-1-thread-2,5,main]: doing work //1554712658620: Thread[pool-1-thread-3,5,main]: doing work }