jdk1.8 J.U.C并发源码阅读------CountDownLatch源码解析

Posted Itzel_yuki

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jdk1.8 J.U.C并发源码阅读------CountDownLatch源码解析相关的知识,希望对你有一定的参考价值。

一、继承关系

public class CountDownLatch
功能:让n个线程(线程之间是共享的关系)等待另外m个线程执行完任务后再开始执行。
具体流程:将n个调用countDownLatch.await()的线程添加到CLH队列中,m个线程中最后一个执行countDownLatch.countDown()方法的线程执行tryReleaseShared成功,唤醒CLH队列中的n个共享线程。


说明:不要求和锁一起使用。初始化时指定m个线程的数量。

二、成员变量

private final Sync sync;//继承自AQS


构造方法:

//指定需要等待的线程的个数
	public CountDownLatch(int count) 
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
    


三、内部类

(1)Sync

private static final class Sync extends AbstractQueuedSynchronizer 
        private static final long serialVersionUID = 4982264981922014374L;
		//构造方法,设置state的个数,表示能获取的锁的个数
        Sync(int count) 
            setState(count);
        

        int getCount() 
            return getState();
        
		//共享锁实现,尝试获取共享锁
        protected int tryAcquireShared(int acquires) 
		//state==0则获取成功,否则失败
            return (getState() == 0) ? 1 : -1;
        
		//释放共享锁。
        protected boolean tryReleaseShared(int releases) 
            for (;;) 
                int c = getState();
                if (c == 0)
                    return false;
				//释放一个共享锁,state减1
                int nextc = c-1;
				//CAS更新state的值
                if (compareAndSetState(c, nextc))
                    return nextc == 0;
            
        
    


四、方法说明

(1)countDown:执行一次,state减1一次,最后执行countDown的线程负责唤醒CLH中等待获取锁的所有共享状态的node中的线程

public void countDown() 
	//调用AQS的releaseShared方法,释放成功则进行doReleaseShared()方法,负责唤醒后继线程。
        sync.releaseShared(1);
    


(2)await:调用AQS的acquireSharedInterruptibly方法,具体为:调用Sync的tryAcquireShared方法尝试获取锁,失败则加入到CLH队列中,在队列中阻塞获取锁。

//中断则抛出异常
	public void await() throws InterruptedException 
        sync.acquireSharedInterruptibly(1);
    


(3)await:调用AQS的acquireSharedInterruptibly方法,具体为:调用Sync的tryAcquireShared方法尝试获取锁,失败则加入到CLH队列中,在队列中阻塞获取锁。

//中断抛出异常,超时则节点状态转换为cancelled
	public boolean await(long timeout, TimeUnit unit)
        throws InterruptedException 
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    

五、使用实例

说明:两个共享线程等待另外5个线程执行任务,当5个线程都执行完成后,这两个共享线程再开始运行

public static void testCountDown()
		CountDownLatch countDownLatch=new CountDownLatch(5);
		Thread[] threads=new Thread[5];
		
		new Thread(new Runnable() 
			
			@Override
			public void run() 
				// TODO Auto-generated method stub
				LockSupport.parkNanos(1000);
				System.out.println("张三开始等待");
				try 
					countDownLatch.await();
				 catch (InterruptedException e) 
					// TODO Auto-generated catch block
					e.printStackTrace();
				
				System.out.println("人到齐了,可以开会!");
			
		).start();
		
		new Thread(new Runnable() 
			
			@Override
			public void run() 
				// TODO Auto-generated method stub
				LockSupport.parkNanos(1000);
				System.out.println("李四开始等待");
				try 
					countDownLatch.await();
				 catch (InterruptedException e) 
					// TODO Auto-generated catch block
					e.printStackTrace();
				
				System.out.println("人到齐了,可以开会!");
			
		).start();
		
		for(int i=1;i<=5;i++)
			threads[i-1]=new myThread("persion"+i, countDownLatch);
			threads[i-1].start();
		
		
	
	
	class myThread extends Thread
	String name;
	CountDownLatch countDownLatch;
	public myThread(String name,CountDownLatch countDownLatch)
		super();
		this.name=name;
		this.countDownLatch=countDownLatch;
	
	@Override
	public void run() 
		// TODO Auto-generated method stub
		try 
			Thread.sleep(2000);
		 catch (InterruptedException e) 
			// TODO Auto-generated catch block
			e.printStackTrace();
		
		System.out.println(name+"来了!");
		countDownLatch.countDown();
	
输出:

张三开始等待
李四开始等待
persion4来了!
persion3来了!
persion2来了!
persion1来了!
persion5来了!
人到齐了,可以开会!
人到齐了,可以开会!




以上是关于jdk1.8 J.U.C并发源码阅读------CountDownLatch源码解析的主要内容,如果未能解决你的问题,请参考以下文章

jdk1.8 J.U.C并发源码阅读------ReentrantLock源码解析

jdk1.8 J.U.C并发源码阅读------ReentrantLock源码解析

jdk1.8 J.U.C并发源码阅读------CountDownLatch源码解析

jdk1.8 J.U.C并发源码阅读------CountDownLatch源码解析

jdk1.8 J.U.C并发源码阅读------CyclicBarrier源码解析

jdk1.8 J.U.C并发源码阅读------CyclicBarrier源码解析