JAVA并发编程之倒计数器CountDownLatch

CountDownLatch 的使用场景:在主线程中开启多线程去并行执行任务,并且主线程需要等待所有子线程执行完毕后汇总返回结果。

我把源码中的英文注释全部删除,写上自己的注释。就剩下 70 行不到的代码,很简单了。

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;

public class CountDownLatch {
    // 自定义一个属性,继承    抽象队列同步器
    private static final class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = 4982264981922014374L;

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

        int getCount() {
            return getState();
        }

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

        @Override
        protected boolean tryReleaseShared(int releases) {
            for (;;) {
                int c = getState();
                if (c == 0) {
                    return false;
                }
                int nextc = c-1;
                if (compareAndSetState(c, nextc)) {
                    return nextc == 0;
                }
            }
        }
    }
    //定义私有属性,该类继承 抽象队列同步器
    private final java.util.concurrent.CountDownLatch.Sync sync;

    // 构造方法,传入数字,用于倒计数
    public CountDownLatch(int count) {
        if (count < 0) {
            throw new IllegalArgumentException("count < 0");
        }
        this.sync = new java.util.concurrent.CountDownLatch.Sync(count);
    }
    // 阻塞当前线程,直到count=0才唤醒线程
    public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }
    // 阻塞当前线程,直到count=0才唤醒线程。
    // 设置定时时间到了,也会唤醒线程。
    public boolean await(long timeout, TimeUnit unit)
            throws InterruptedException {
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    }
    //count 减 1
    public void countDown() {
        sync.releaseShared(1);
    }
    //获取 count
    public long getCount() {
        return sync.getCount();
    }
    //toString方法,获取字符串
    public String toString() {
        return super.toString() + "[Count = " + sync.getCount() + "]";
    }
}

我用这个CountDownLatch来实现多线程执行任务,合并结果返回。

//创建线程池
        ExecutorService pool = Executors.newCachedThreadPool();
        //定义集合存储结果
        List values = new ArrayList<>();
        //定义倒计数器
        CountDownLatch count = new CountDownLatch(2);

        //线程池执行任务1
        pool.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    //线程池进行计算1,得到结果1。
                    String value1 = "结果1";
                    //把结果加入共享变量中。
                    values.add(value1);
                } catch (Exception e) {
                    e.printStackTrace();
                }finally {
                    //finally 中保证一定会执行 减1
                    //计数器减 1
                    count.countDown();
                }

            }
        });

        //线程池执行任务2
        pool.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    //线程池进行计算2,得到结果2。
                    String value2 = "结果2";
                    //把结果加入共享变量中。
                    values.add(value2);
                } catch (Exception e) {
                    e.printStackTrace();
                }finally {
                    //finally 中保证一定会执行 减1
                    //计数器减 1
                    count.countDown();
                }

            }
        });
        //线程阻塞等待
        count.await();

        //返回多线程执行的结果。
        return values; 
  
 

 

  多线程并发编程,就是这么简单!不用Callable,也能获取到线程池的返回值哦。

 

你可能感兴趣的:(JAVA并发编程之倒计数器CountDownLatch)