java多线程解说【拾伍】_并发工具类:CountDownLatch

上篇文章:java多线程解说【拾肆】_线程池


从JDK5开始,java为我们的多线程开发提供了多种并发工具,最常用的是如下三个:


1.CountDownLatch

2.CyclicBarrier

3.Semaphore


本文先介绍一下CountDownLatch


CountDownLatch


CountDownLatch可以在如下的场景使用:当一个线程需要在另外若干个线程执行完毕后再执行时。当然我们也可以使用join()方法来实现,但是这需要去逐个线程等待,而且各个线程是串行运行的。CountDownLatch的实现是等待一个信号量count,每当线程执行一次CountDownLatch.countDown()方法时,CountDownLatch就将count-1,直到count为0时,将唤醒执行CountDownLatch.await()处的线程。


一个例子


public class TestCountDownLatch {
	
	private static CountDownLatch countDownLatch = new CountDownLatch(5);

	
	public static void main(String[] args) {
		
		Thread waitThread = new Thread(){
            @Override
            public void run() {
            	try {
            		System.out.println("waitThread线程在等待执行");
            		TestCountDownLatch.countDownLatch.await();
            		System.out.println("5个线程执行完毕,waitThread执行");
				} catch (Exception e) {
					e.printStackTrace();
				}
            }
        };
        waitThread.start();
		for (int i = 0; i < 5; i++) {
			Thread thread = new Thread(){
	            @Override
	            public void run() {
	            	try {
	            		TestCountDownLatch.countDownLatch.countDown();
	            		System.out.println("线程"+this.getName()+"准备就绪");
					} catch (Exception e) {
						e.printStackTrace();
					}
	            }
	        };
	        thread.start();
		}
		
		
	}
}

上述代码执行的结果为:


线程Thread-1准备就绪
waitThread线程在等待执行
线程Thread-2准备就绪
线程Thread-4准备就绪
线程Thread-3准备就绪
线程Thread-5准备就绪
5个线程执行完毕,waitThread执行



由此可知,waitThread是等待5个线程都执行完毕后才开始执行await()后面的代码的。



常用API


// 使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断。
void await()
// 使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断或超出了指定的等待时间。
boolean await(long timeout, TimeUnit unit)
// 递减锁存器的计数,如果计数到达零,则释放所有等待的线程。
void countDown()
// 返回当前计数。
long getCount()


实现分析


CountDownLatch内部维护了一个Sync对象,Sync继承于AbstractQueuedSynchronizer(AQS)。在AQS中维护了一个private volatile long类型的变量state。对于CountDownLatch而言,锁计数器即通过state实现的。CountDownLatch中的getCount()最终是调用AQS中的getState(),返回的state对象即锁计数器。


CountDownLatch的await()实际上就是尝试去获取共享锁,获取不到则一直等待,获取到的条件就是state=0;而countDown()实际上调用releaseShared(1),让state-1。


这里需要注意的是,CountDownLatch只能使用一次,也就是说当count=0后就无法继续使用了。那么如果我们想重复使用该怎么办,请看下一文:


java多线程解说【拾陆】_并发工具类:CyclicBarrier


你可能感兴趣的:(多线程,java多线程解说)