多线程CountDownLatch

1.简单的使用

//  CountDownLatch 需要注意的地方有三个地方,如代码中标注
// 当前代码执行时会阻塞的 因为在 ② 中设置的值为 4 ,但只有3个线程过来,所以一直在阻塞
// 就像打麻将一样,还差一个人
public class CountdownLatchTest implements Runnable{
	CountDownLatch countDownLatch;
	public CountdownLatchTest(CountDownLatch countDownLatch) {
		this.countDownLatch = countDownLatch;	
	}
	@Override
	public void run() {
		try {
			Thread.sleep(500);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("CountDownLatch peform ..."+Thread.currentThread().getName());
		countDownLatch.countDown();  //  注意 ①
		
	}
	
	public static void main(String[] args) throws InterruptedException {
		CountDownLatch countDownLatch = new CountDownLatch(4);   //  注意 ②
		for(int i = 0; i < 3; i++){  // 注意 ③
			Thread thread = new Thread(new CountdownLatchTest(countDownLatch));
			thread.start();
			Thread.currentThread().sleep(500);
		}
		System.out.println("等待线程完成...");
		countDownLatch.await();  // 注意 ④
		System.out.println("countDownLatch 执行完成");
	}

}

2.看看源码吧

 /**
     * Synchronization control For CountDownLatch.
     * Uses AQS state to represent count.
     */
    private static final class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = 4982264981922014374L;

        Sync(int count) {
            setState(count);
        }

        int getCount() {
            return getState();
        }

        protected int tryAcquireShared(int acquires) {
            return (getState() == 0) ? 1 : -1;
        }

        protected boolean tryReleaseShared(int releases) {
            // Decrement count; signal when transition to zero
            for (;;) {
                int c = getState();
                if (c == 0)
                    return false;
                int nextc = c-1;
                if (compareAndSetState(c, nextc))
                    return nextc == 0;
            }
        }
    }

CountDownLatch 里面定义了一个类 Sync,这个类 Sync 继承了 AbstractQueuedSynchronizer,它的初始化调用的时 setState 方法,getCount调用的是getState方法。

当每执行一次 countDown 方法时,它都会释放一份资源,调用方法过程为:
外部调用 countDown 方法 --> 内部调用父类 releaseShared 方法,并传入参数1(表示释放一份锁资源)—>调用 tryReleaseShared 方法,并传来参数 1,tryReleaseShared 方法由子类实现 —> 真正实现在子类中,代码如下: 死循环获取当前锁资源数量

 protected boolean tryReleaseShared(int releases) {  // 传入需要释放的资源数量,这里是 1 
            // Decrement count; signal when transition to zero
            for (;;) {
                int c = getState();	// 得到计数器中的值
                if (c == 0)
                    return false;
                int nextc = c-1;		// 通过减法
                if (compareAndSetState(c, nextc))		// 将更改后的值重新设置进去
                    return nextc == 0;  // 这里判断是否锁资源释放完了,这里决定了是否还会继续阻塞下去,如下代码
            }
        }
public final boolean releaseShared(int arg) {
        if (tryReleaseShared(arg)) {  // 更具返回值,决定死否释放资源
            doReleaseShared();  // 释放资源,线程继续,如果不能理解的话,建议去看看AQS源码,会比较难,但看完 AQS 后看这个会感觉好简单
            return true;
        }
        return false;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值