zoukankan      html  css  js  c++  java
  • 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<Object> 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,也能获取到线程池的返回值哦。

  • 相关阅读:
    php基础的一点注意事项
    每天学习一点点--word-break和word-wrap用法和区别
    line-height的一点粗浅认识
    图片的无缝滚动效果
    CSS篇章
    redis 3.0 集群__数据迁移和伸缩容
    redis 3.0 集群__使用
    官方教程文档地址
    redis 3.0 集群__安装
    java 泛型的使用
  • 原文地址:https://www.cnblogs.com/itbac/p/11296534.html
Copyright © 2011-2022 走看看