CountDownLatch也叫闭锁,在JDK1.5被引入,允许一个或多个线程等待其他线程完成操作后再执行。
CountDownLatch内部会维护一个初始值为线程数量的计数器,主线程执行await方法,如果计数器大于0,则阻塞等待。
当一个线程完成任务后,计数器值减1。当计数器为0时,表示所有的线程已经完成任务,等待的主线程被唤醒继续执行。
CountDownLatch使用AQS的方式与Semaphore相似:在同步状态中保存的是当前的计数值。
闭锁的作用:
确保某个计算在其需要的所有资源都被初始化之后才继续执行。
确保某个服务在其依赖的所有其他服务都已经启动之后才启动。
等待直到某个操作的所有参与者都就绪再继续执行。
CountDownLatch还可以实现类似计数器的功能。比如有一个任务A,它要等待其他4个任务执行完毕之后才能执行,此时就可以利用CountDownLatch来实现这种功能了。
和CyclicBarrier的区别:
CyclicBarrier 允许一系列线程相互等待对方到达一个点,正如 barrier 表示的意思,该点就像一个栅栏,先到达的线程被阻塞在栅栏前,必须等到所有线程都到达了才能够通过栅栏;
CyclicBarrier 持有一个变量 parties,表示需要全部到达的线程数量;先到达的线程调用 barrier.await 方法进行等待,一旦到达的线程数达到 parties 变量所指定的数,栅栏打开,所有线程都可以通过;
CyclicBarrier 构造方法接受另一个 Runnable 类型参数 barrierAction,该参数表明再栅栏被打开的时候需要采取的动作,null 表示不采取任何动作,注意该动作将会在栅栏被打开而所有线程接着运行前被执行;
CyclicBarrier 是可重用的,当最后一个线程到达的时候,栅栏被打开,所有线程通过之后栅栏重新关闭,进入下一代;
CyclicBarrier.reset 方法能够手动重置栅栏,此时正在等待的线程会收到 BrokenBarrierException异常。
1 public class Test { 2 public static void main(String[] args) { 3 final CountDownLatch latch = new CountDownLatch(2); 4 5 new Thread(){ 6 public void run() { 7 try { 8 。。。 9 latch.countDown(); 10 } catch (InterruptedException e) { 11 e.printStackTrace(); 12 } 13 }; 14 }.start(); 15 16 new Thread(){ 17 public void run() { 18 try { 19 。。。 20 latch.countDown(); 21 } catch (InterruptedException e) { 22 e.printStackTrace(); 23 } 24 }; 25 }.start(); 26 27 try { 28 System.out.println("等待2个子线程执行完毕..."); 29 latch.await(); 30 System.out.println("2个子线程已经执行完毕"); 31 System.out.println("继续执行主线程"); 32 } catch (InterruptedException e) { 33 e.printStackTrace(); 34 } 35 } 36 }