countDownLatch作用是使一/多个线程等待其他线程执行完成后再执行,保证线程的执行顺序
countDownLatch定义一个计数器和阻塞队列。当前线程执行await会将他放到阻塞队列中,只有计数器递减至0阻塞队列中线程才会执行;或者在需要阻塞的线程执行await(long timeout, TimeUint unit)会在timeout时间之后当前线程可以执行
由于coutDownLatch可以保证线程执行顺序,所以适用于解决那些一个/多个线程在执行之前必须依赖某些必要的前提业务限制性的场景
demo1:
public class FirstDemo { public static int count=0; public static AtomicInteger atomicInteger=new AtomicInteger(0); public static void main(String[] args) throws InterruptedException { //CountDownLatch countDownLatch=new CountDownLatch(1); Runnable runnable=new Runnable() { @Override public void run() { for(int i=0;i<10;i++){ count++; atomicInteger.getAndIncrement(); System.out.println("this is sub thread"+count); } //countDownLatch.countDown(); } }; for(int i=0;i<5;i++){ new Thread(runnable).start(); } //countDownLatch.await(); System.out.println("this is main thread"); } }
执行结果如下,可见主线程打印并没有等到线程执行完后才打印
...
this is sub thread17
this is sub thread18
this is sub thread19
this is sub thread20
this is main thread
this is sub thread21
this is sub thread22
...
demo2:
下例中,parallel1必须依赖parallel2 parallel3执行完之后才可以执行
public class CountDownLatchDemo { private static CountDownLatch countDownLatch=new CountDownLatch(2); public static void main(String[] args) throws InterruptedException {
Thread parallel1=new Thread(new Runnable() { @SneakyThrows @Override public void run() { System.out.println("this is parallel one"); countDownLatch.await(); //await()作用是阻塞当前线程。线程parallel1处于阻塞状态 System.out.println("begin to execute parallel one"); } }); Thread parallel2=new Thread(new Runnable() { @Override public void run() { System.out.println("this is parallel two"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } countDownLatch.countDown(); //countDown()对计数器countdowlatch进行减一操作,当计数器递减至0,阻塞的线程parallel1才会执行,如果计数器一直没有递减至0那么阻塞队列中中线程prallel1会一直得不到执行 } }); Thread parallel3=new Thread(new Runnable() { @Override public void run() { System.out.println("this is parallel three"); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } countDownLatch.countDown(); } }); System.out.println("main thread starting..."); parallel1.start(); Thread.sleep(2000); parallel2.start(); parallel3.start(); } }
执行结果:
main thread starting...
this is parallel one
this is parallel two
this is parallel three
begin to execute parallel one
Process finished with exit code 0
CountdownLatch常用方法
CountDownLatch(int cout):构造计数器
await(): 将当前线程放到阻塞队列中,当计数器将为-0或者过了超时时间才会继续执行当前线程
await(long timeout, TimeUnit timeUnit):超过timeout时间,即便计数器没有将为0也会执行阻塞队列中线程
countdown(): 计数器减一操作
参考文献:
https://www.jianshu.com/p/3c6315b4923b