JDK 源码复习 concurrent 包 03 CyclicBarrier

 

CyclicBarrier 例子:
    /**
     * 实现功能是将goodsReqDtoList作为calcEstimateAmount方法的入参,然后将最终的结果放入map中进行返回
     * 1.根据 goodsReqDtoList 的长度,判断我们要开多少个线程
     * 2.将每个线程获得的结果放入 map 中,等到所有线程都计算完,将结果进行返回
     * @param goodsReqDtoList CommonGoodsReqDto,支持多个商品属性的查询
     * @return
     */
    @Override
    public Map<String, Long> getRebatePlanAmount(List<CommonGoodsReqDto> goodsReqDtoList) {
        // 线程执行数量,判断要开多少个线程执行
        int threadNum;
        int everyListCount = 5; // 每个list中有5条数据
        if (goodsReqDtoList.size() % everyListCount == 0) {
            threadNum = goodsReqDtoList.size() / everyListCount;
        } else {
            threadNum = goodsReqDtoList.size() / everyListCount + 1;
        }

        final Map<String, Long> resMap = new ConcurrentHashMap<>();
        final CyclicBarrier cyclicBarrier = new CyclicBarrier(threadNum);
        List<CommonGoodsReqDto> goodsList = new ArrayList<>();
        for (int i = 0; i < goodsReqDtoList.size(); i++) {
            goodsList.add(goodsReqDtoList.get(i));
            if ((i == goodsReqDtoList.size() - 1) || (i + 1) % everyListCount == 0) {
                final List list = goodsList;
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        // 将每个线程获得的结果放到 resMap 中
                        resMap.putAll(calcEstimateAmount(list));
                        try {
                            cyclicBarrier.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        } catch (BrokenBarrierException e) {
                            e.printStackTrace();
                        }
                        System.out.println("AAA");
                    }
                }).start();
            }
            if ((i + 1) % everyListCount == 0) {
                goodsList = new ArrayList<>();
            }
        }
        return resMap;
    }
源码分析:

https://www.cnblogs.com/leesf456/p/5392816.html

二、CyclicBarrier数据结构

  分析源码可以知道,CyclicBarrier底层是基于ReentrantLockAbstractQueuedSynchronizer来实现的,所以,CyclicBarrier的数据结构也依托于AQS的数据结构,在前面对AQS的分析中已经指出了其数据结构,在这里不再累赘。

执行过程如下:

1.首先使用ReentrantLock加锁 

    lock.lock();

2.获取当前generation

3.判断如果屏障 被破坏,就抛出异常BrokenBarrierException

4. 判断如果线程被中断,调用breakBarrier损坏屏障,并且唤醒所有的线程,同时抛出线程中断异常

5.int index = --count; 减少正在等待进入屏障的线程的数量,也就是代表增加了已进入线程的屏障数量

6.如果index==0,代表所有线程都进入了屏障,开始运行对应的command,调用command.run()

7.然后进入下一代 nextGeneration

8.进入for无限循环,如果没有设置等待时间,就 trip.await();进行等待;如果设置了等待时间,

  就trip.awaitNanos(nanos);等待一段时间;await()底层是调用LockSupport.park() 锁住

  死循环终止的条件:屏障broken,线程中断interrupted,或者超时

countdowlatch 和 cyclicbarrier 的内部原理和用法,以及相互之间的差别。

CountDownLatch是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它运行一个或者多个线程一直处于等待状态。
CyclicBarrier要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续运行。
CyclicBarrier初始化的时候,设置一个屏障数。线程调用await()方法的时候,这个线程就会被阻塞,当调用await()的线程数量到达屏障数的时候,主线程就会取消所有被阻塞线程的状态。
前者是递减,不可循环,后者是递加,可循环用
countdowlatch 基于abq cb基于ReentrantLock Condition

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值