CountDownLatch使用及实现原理

CountDownLatch是Java提供的线程递减锁,为开发人员封装出来针对特殊场景使用的工具类,主要用在某一个动作的执行以来其他动作对应线程的完成。

使用步骤:

1.拿到一个CountDownLatch实例,初始化大小为依赖的动作线程数

2.将CountDownLatch实例传递给依赖线程

3.在依赖线程执行完对应的动作后调用CountDownLatch.countDown方法

4.在主线程中调用CountDownLatch.await方法

package com.jv.parallel.feature;

import java.util.concurrent.CountDownLatch;

/*
 * 线程递减锁,用来控制某一个动作的执行依赖其他动作线程的完成
 * 
 * 例如:开始钓鱼之前先要做主线、拌饵料、打窝子
 */
public class TestCountDownLatch {
	public static void main(String[] args) throws InterruptedException {
		// 1.声明一个线程递减锁
		// 因为在钓鱼
		CountDownLatch cdl = new CountDownLatch(3);
		new Thread(new TieLine(cdl)).start();
		new Thread(new MixedFood(cdl)).start();
		new Thread(new Feed(cdl)).start();
		cdl.await();
		System.out.println("开始愉快的钓鱼了");
	}
	
	/*
	 * 制作钓鱼的主线
	 */
	static class TieLine implements Runnable{
		CountDownLatch cdl;
		public TieLine(CountDownLatch cdl) {
			this.cdl = cdl;
		}

		@Override
		public void run() {
			System.out.println("制作4.5的主线");
			cdl.countDown();
		}
		
	}
	
	/*
	 * 拌饵料
	 */
	static class MixedFood implements Runnable{
		CountDownLatch cdl;
		public MixedFood(CountDownLatch cdl) {
			this.cdl = cdl;
		}

		@Override
		public void run() {
			System.out.println("拌饵料");
			cdl.countDown();
		}
	}
	
	/*
	 * 做窝子
	 */
	static class Feed implements Runnable{
		CountDownLatch cdl;
		public Feed(CountDownLatch cdl) {
			this.cdl = cdl;
		}

		@Override
		public void run() {
			System.out.println("打窝子");
			cdl.countDown();
		}
	}
}

CountDownLatch核心是使用了一个继承AbstractQueuedSynchronizer的同步器,这种设计模式称之为模板方法(在抽象类中定义算法的骨架,由子类实现骨架中具体的方法),模板方法设计模式可以参阅模板方法

CountDownLatch.await方法

    public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }

同步器的acquireSharedInterruptibly方法其实是CountDownLatch.Syn父类AbstractQueuedSynchronizer的,它就是一个算法骨架

    public final void acquireSharedInterruptibly(int arg)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        if (tryAcquireShared(arg) < 0)
            doAcquireSharedInterruptibly(arg);
    }

acquireSharedInterruptibly的核心就是调用子类实现的tryAcquireShared

再看CountDownLatch.Syn中实现的抽象方法tryAcquireShared,tryReleaseShared

        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.countDown方法

    public void countDown() {
        sync.releaseShared(1);
    }

同步器的releaseShared方法其实是CountDownLatch.Syn父类AbstractQueuedSynchronizer的,它也是一个算法骨架

    public final boolean releaseShared(int arg) {
        if (tryReleaseShared(arg)) {
            doReleaseShared();
            return true;
        }
        return false;
    }

releaseShared的核心就是调用子类实现的tryReleaseShared

猜你喜欢

转载自my.oschina.net/u/3049601/blog/1808526