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来了!
人到齐了,可以开会!
人到齐了,可以开会!




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值