等待多线程完成的CountDownLatch

1,322 阅读2分钟

一、简介

CountDownLatch构造方法接受一个int类型的参数作为计数器,如果你想等待N个点完成,这里就传入N

每调用一次CountDownLatch的countDown()方法时,N就会减1,CountDownLatch的await()方法会阻塞当前线程,直到N = 0

由于countDown()方法可以用在任何地方,所以这里说的N,可以是N个线程,也可以是1个线程里的N个执行步骤。用在多个线程时,只需要把这个CountDownLatch的引用传递到线程里即可。

如果在某个解析sheet的线程处理得比较慢,不可能让主线程一直等待,所以可以使用另外一个带指定时间的await()方法——await(long time, TimeUnit unit),这个方法等待特定时间后,就会不再阻塞当前线程。join()也有类似的方法。


注意:计数器必须大于等于0,只是等于0时候,计数器就是0,调用await()方法时不会阻塞当前线程CountDownLatch不可能重新初始化或则修改CountDownLatch对象的内部计数器的值一个线程调用countDown()方法happen-before另外一个线程调用await()方法。


2、实例

需要三个线程分别循环按顺序打印出a,b,c,d,e,f,g,h,i,即线程1打印a,d,g;线程2打印b,e,h;线程3打印c,f,i。

import java.util.concurrent.*;

public class test {

	static CountDownLatch a = new CountDownLatch(1);
	static CountDownLatch b = new CountDownLatch(1);
	static CountDownLatch c = new CountDownLatch(1);
	
	static class runnable1 implements Runnable{
		@Override
		public void run() {
			try {
				System.out.println("a");
				b.countDown();
				a.await();
				System.out.println("d");
				a = new CountDownLatch(1);
				b.countDown();
				a.await();
				System.out.println("g");
				b.countDown();
			} catch(Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	static class runnable2 implements Runnable{
		@Override
		public void run() {
			try {
				b.await();
				System.out.println("b");
				b = new CountDownLatch(1);
				c.countDown();
				b.await();
				System.out.println("e");
				b = new CountDownLatch(1);
				c.countDown();
				b.await();
				System.out.println("h");
				c.countDown();
			} catch(Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	static class runnable3 implements Runnable{
		@Override
		public void run() {
			try {
				c.await();
				System.out.println("c");
				c = new CountDownLatch(1);
				a.countDown();
				c.await();
				System.out.println("f");
				c = new CountDownLatch(1);
				a.countDown();
				c.await();
				System.out.println("i");
			} catch(Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void main(String[] args){
		Thread thread1 = new Thread(new runnable1());
		Thread thread2 = new Thread(new runnable2());
		Thread thread3 = new Thread(new runnable3());
		
		thread1.start();
		thread2.start();
		thread3.start();
	}
}