为了解决多线程问题,java.util.concurrent包从Java SE5开始引入了一个新类CountDownLatch。其功能主要用来同步多个任务的执行顺序,CountDown的意思是倒数计秒,Latch做为名词有门闩和锁存器的意思。
锁存器的最主要作用是缓存,其次完成高速的控制其与慢速的外设的不同步问题,再其次是解决驱动的问题,最后是解决一个 I/O 口既能输出也能输入的问题。
因此,顾名思义,CountDownLatch可以在倒数计时期间保持多个任务的执行状态,倒计时结束时便可以解锁并唤醒其他任务。
CountDownLatch最典型的应用就是将一个大的任务分解成N个子任务,当N个子任务执行完毕后可以唤起下一个大任务。
我们将N作为倒数记时的时间来初始化一个CoutDownLatch对象,然后每当一个子任务完成时,可以将N减1,等到N为0的时候,其他正在等待的任务便可以wake up。
Package
import java.util.concurrent.*;
首先,定义一个子任务TaskPortion
private static Random rand = new Random(47); private final CountDownLatch latch; TaskPortion(CountDownLatch latch) { this.latch = latch; } public void run() { try { doWork(); latch.countDown(); } catch (InterruptedException e) { // Acceptable way to exit } } public void doWork() throws InterruptedException { TimeUnit.MILLISECONDS.sleep(rand.nextInt(2000)); System.out.println(this + "completed"); } public String toString() { return String.format("%1$-3d", id); } }
// Waits on the CountDownLatch class WaitingTask implements Runnable { private static int counter = 0; private final int id = counter++; private final CountDownLatch latch; WaitingTask(CountDownLatch latch) { this.latch = latch; } public void run() { try { latch.await(); System.out.println("Latch barrier passed for " + this); } catch (InterruptedException ex) { System.out.println(this + " interrupted"); } } public String toString() { return String.format("WaitingTask %1$-3d ", id); } }
public class CountDownLatchDemo { static final int SIZE = 10; public static void main(String[] args) throws Exception { ExecutorService exec = Executors.newCachedThreadPool(); // All must share a single CountDownLatch object: CountDownLatch latch = new CountDownLatch(SIZE); for (int i = 0; i < 10; i++) { exec.execute(new WaitingTask(latch)); } for (int i = 0; i < SIZE; i++) { exec.execute(new TaskPortion(latch)); } System.out.println("Launched all tasks"); exec.shutdown(); // Quit when all tasks complete } }