CompletableFuture parallelStream并行流使用的一个注意事项

22 篇文章 0 订阅
12 篇文章 1 订阅

并行流 就是多线程 使用的威力大,出问题的概率也大,使用时候要谨慎,一旦出问题,

相对来说不好排查错误

这里就说一个遇到的问题: 不要再每个并行流分别计算,这个流处理需要的公共变量,

可以在外部计算好,传进去。

修改前:

上图函数具体实现

修改后:

 

类似的一个修改

 

 

最后给出具体获取

List<String> catServiceNames = catService.getCatServiceNames(); 方法 看看为什么导致并发

代码如下

List<String>  appNameList = null ;
    public List<String> getCatServiceNames() {
        List<String> res = null;
        res = appNameList != null ? appNameList : getCatServiceNamesPeriod();
        return  res ;
    }

 

下图代码大致说明

message集合是取自远程io操作获取
serviceList 来自redis 优先级是redis ,涉及到serviceList 和message合并
finalServiceList是最终需要的数据集合,也是返回值,

所以这个操作首先不论是否耗时多少(其实不多),但是由于多个并行操作,可能对一些状态的判断会出现问题,

导致redis 存储的数据有变化,一些脏数据

有可能线程1 本来拿到redis 应该是拿到线程2

 @Scheduled(cron= "0 0/1 * * * ?") //每5分钟执行一次
    public  List<String> getCatServiceNamesPeriod() {
//        String url = configService.getCatRealUrl()+"/cat/r/state?domain=cat&ip=All&show=true";
        String url = configService.getCatUrl()+"/cat/r/state?domain=cat&ip=All&show=true";
        Document doc;
        List<String> message = new ArrayList<>();
        //最终结果 返回的
        List<String> finalServiceList = new ArrayList<>();
        try {
            doc = Jsoup.connect(url).timeout(500000).get();
            //根据class取值 table.table table-hover table-striped table-condensed 这样取不到值
            //只能按照下面的方式操作 并且本来应该是get(0) 反而要用get(1) 原因有空再看
            Element table = doc.select("table.table").get(1);
            Elements trList = table.select("tr");
            Elements needDeal = new Elements();
            for (Element tr : trList) {
                if (tr.select("td").size() == 7) {
                    needDeal.add(tr);
                }
            }
            //needDeal==1 说明没有项目接入cat当前环境 第一个不是的
            if (needDeal.size() == 1) {

            } else {
                //从第二个元素 遍历,第一个不是需要的数据。
                for (int i = 1; i < needDeal.size(); i++) {
//                    System.out.println(b.toJson(needDeal.get(i).select("td").first().text()));
                    if(! needDeal.get(i).select("td").last().text().equals("[]"))
                          message.add(needDeal.get(i).select("td").first().text());
                }
            }
            //从页面得到的list要和redis里面信息合并 页面可能不是最全的 redis里面数据是递增的
            ListOperations listOperations = shardingStringRedisTemplate.opsForList();
            List<String> serviceList = listOperations.range(RadonConstants.redis_service_list, 0, -1);

            // redis 缓存 serviceList 优先级高于 message 本地缓存
            if(message == null){//cat服务器挂了
                if(serviceList==null || serviceList.size()==0){ //redis也没数据了 极端的极端
                    //还是主动放一个值
                    message.add("radon");
                    finalServiceList = message;
                }else {
                    finalServiceList = serviceList;
                }
            }else if(message != null){
                if(serviceList==null || serviceList.size()==0){
                    listOperations.rightPushAll(RadonConstants.redis_service_list, message);
                    finalServiceList = message;//返回值需要 赋值
                }else {
                    message.stream().forEach(name->{
                        if (!serviceList.contains(name)) {
                            serviceList.add(name);
                        }
                    });
                    //删除 由redisTemplate来控制
                    shardingStringRedisTemplate.delete(RadonConstants.redis_service_list);
                    //重新赋值 保持最新
                    listOperations.rightPushAll(RadonConstants.redis_service_list, serviceList);
                    finalServiceList = serviceList;
                }
            }
            return  finalServiceList;
        }catch (Exception e){
            return null;
        }finally {
            //赋值全局变量
            if (finalServiceList != null && finalServiceList.size() > 0) {
                appNameList = finalServiceList;
            }
        }
    }

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值