老板说再用Lambda并发流,明天就不用来了

2 篇文章 0 订阅
2 篇文章 0 订阅
1、前言

Java8的stream接口极大地减少了for循环写法的复杂性,stream提供了map/reduce/collect等一系列聚合接口,还支持并发操作:parallelStream。

Java8的paralleStream用fork/join框架提供了并发执行能力。但是如果使用不当,很容易陷入误区。

2、parallelStream并发流线程安全问题
@Test
public void test3() {
    List<Integer> param = Lists.newArrayList();
    for (int i = 0; i < 100; i++) {
        param.add(i);
    }
    log.info("for循环的入参长度为:{}", param.size());
    for (int i = 0; i < 50; i++) {
        List<Integer> resultList = Lists.newArrayList();
        Map<Integer, Integer> resultMap = Maps.newHashMap();
        param.parallelStream()
            .forEach(v -> {
                resultList.add(v);
                resultMap.put(v, v);
            });
        System.out.println("i="+i+"的结果数据为:resultList长度="+resultList.size()+";resultMap长度="+resultMap.size());
    }
}
3、输出结果
2023-01-17 17:03:41.372  INFO 8552 --- [           main] c.q.r.p.management.clander.CalendarTest  : for循环的入参长度为:100
i=0的结果数据为:resultList长度=98;resultMap长度=99
i=1的结果数据为:resultList长度=100;resultMap长度=99
i=2的结果数据为:resultList长度=100;resultMap长度=99
i=3的结果数据为:resultList长度=99;resultMap长度=99
i=4的结果数据为:resultList长度=99;resultMap长度=98
i=5的结果数据为:resultList长度=99;resultMap长度=96
i=6的结果数据为:resultList长度=100;resultMap长度=99
i=7的结果数据为:resultList长度=100;resultMap长度=100
i=8的结果数据为:resultList长度=100;resultMap长度=100
i=9的结果数据为:resultList长度=99;resultMap长度=100
i=10的结果数据为:resultList长度=100;resultMap长度=97
i=11的结果数据为:resultList长度=100;resultMap长度=100
i=12的结果数据为:resultList长度=98;resultMap长度=98
i=13的结果数据为:resultList长度=97;resultMap长度=98
i=14的结果数据为:resultList长度=99;resultMap长度=98
i=15的结果数据为:resultList长度=99;resultMap长度=97
i=16的结果数据为:resultList长度=100;resultMap长度=100
i=17的结果数据为:resultList长度=100;resultMap长度=100
i=18的结果数据为:resultList长度=97;resultMap长度=97
i=19的结果数据为:resultList长度=100;resultMap长度=100
i=20的结果数据为:resultList长度=98;resultMap长度=99
i=21的结果数据为:resultList长度=100;resultMap长度=100
i=22的结果数据为:resultList长度=99;resultMap长度=100
i=23的结果数据为:resultList长度=99;resultMap长度=97
i=24的结果数据为:resultList长度=96;resultMap长度=97
i=25的结果数据为:resultList长度=100;resultMap长度=100
i=26的结果数据为:resultList长度=100;resultMap长度=99
i=27的结果数据为:resultList长度=99;resultMap长度=99
i=28的结果数据为:resultList长度=100;resultMap长度=100
i=29的结果数据为:resultList长度=99;resultMap长度=99
i=30的结果数据为:resultList长度=98;resultMap长度=97
i=31的结果数据为:resultList长度=99;resultMap长度=98
i=32的结果数据为:resultList长度=99;resultMap长度=99
i=33的结果数据为:resultList长度=100;resultMap长度=98
i=34的结果数据为:resultList长度=100;resultMap长度=99
i=35的结果数据为:resultList长度=100;resultMap长度=100
i=36的结果数据为:resultList长度=98;resultMap长度=100
i=37的结果数据为:resultList长度=98;resultMap长度=98
i=38的结果数据为:resultList长度=99;resultMap长度=99
i=39的结果数据为:resultList长度=99;resultMap长度=98
i=40的结果数据为:resultList长度=96;resultMap长度=97
i=41的结果数据为:resultList长度=99;resultMap长度=99
i=42的结果数据为:resultList长度=98;resultMap长度=100
i=43的结果数据为:resultList长度=100;resultMap长度=99
i=44的结果数据为:resultList长度=100;resultMap长度=100
i=45的结果数据为:resultList长度=99;resultMap长度=99
i=46的结果数据为:resultList长度=99;resultMap长度=97
i=47的结果数据为:resultList长度=96;resultMap长度=99
i=48的结果数据为:resultList长度=99;resultMap长度=99
i=49的结果数据为:resultList长度=97;resultMap长度=100
4、结论

由输出结果可知,在使用parallelStream流的使用操作线程不安全的ArrayList和HashMap很容易造成数据丢失

5、解决方案
 @Test
public void test5() {
    List<Integer> param = Lists.newArrayList();
    for (int i = 0; i < 100; i++) {
        param.add(i);
    }
    log.info("for循环的入参长度为:{}", param.size());
    for (int i = 0; i < 50; i++) {
        List<Integer> resultList = Lists.newArrayList();
        Map<Integer, Integer> resultMap = Maps.newHashMap();
        param.parallelStream().collect(Collectors.toList()).forEach(v->{
            resultList.add(v);
            resultMap.put(v, v);
        });
        System.out.println("i="+i+"的结果数据为:resultList长度="+resultList.size()+";resultMap长度="+resultMap.size());
    }
}

@Test
public void test4(){
    List<Integer> param = Lists.newArrayList();
    for (int i = 0; i < 100; i++) {
        param.add(i);
    }
    log.info("for循环的入参长度为:{}", param.size());
    for (int i = 0; i < 50; i++) {
        //注意此处,不过不建议这样使用,加锁的话会造成性能降低,实际可以自行测试
        Vector<Integer> resultList = new Vector();
        Map<Integer, Integer> resultMap = Collections.synchronizedMap(Maps.newHashMap());
        param.parallelStream()
            .forEach(v -> {
                resultList.add(v);
                resultMap.put(v, v);
            });
        System.out.println("i="+i+"的结果数据为:resultList长度="+resultList.size()+";resultMap长度="+resultMap.size());
    }
}

输出结果[性能自行测试]
2023-01-17 17:19:31.518  INFO 19220 --- [           main] c.q.r.p.management.clander.CalendarTest  : for循环的入参长度为:100
i=0的结果数据为:resultList长度=100;resultMap长度=100
i=1的结果数据为:resultList长度=100;resultMap长度=100
i=2的结果数据为:resultList长度=100;resultMap长度=100
i=3的结果数据为:resultList长度=100;resultMap长度=100
i=4的结果数据为:resultList长度=100;resultMap长度=100
i=5的结果数据为:resultList长度=100;resultMap长度=100
i=6的结果数据为:resultList长度=100;resultMap长度=100
i=7的结果数据为:resultList长度=100;resultMap长度=100
i=8的结果数据为:resultList长度=100;resultMap长度=100
i=9的结果数据为:resultList长度=100;resultMap长度=100
i=10的结果数据为:resultList长度=100;resultMap长度=100
i=11的结果数据为:resultList长度=100;resultMap长度=100
i=12的结果数据为:resultList长度=100;resultMap长度=100
i=13的结果数据为:resultList长度=100;resultMap长度=100
i=14的结果数据为:resultList长度=100;resultMap长度=100
i=15的结果数据为:resultList长度=100;resultMap长度=100
i=16的结果数据为:resultList长度=100;resultMap长度=100
i=17的结果数据为:resultList长度=100;resultMap长度=100
i=18的结果数据为:resultList长度=100;resultMap长度=100
i=19的结果数据为:resultList长度=100;resultMap长度=100
i=20的结果数据为:resultList长度=100;resultMap长度=100
i=21的结果数据为:resultList长度=100;resultMap长度=100
i=22的结果数据为:resultList长度=100;resultMap长度=100
i=23的结果数据为:resultList长度=100;resultMap长度=100
i=24的结果数据为:resultList长度=100;resultMap长度=100
i=25的结果数据为:resultList长度=100;resultMap长度=100
i=26的结果数据为:resultList长度=100;resultMap长度=100
i=27的结果数据为:resultList长度=100;resultMap长度=100
i=28的结果数据为:resultList长度=100;resultMap长度=100
i=29的结果数据为:resultList长度=100;resultMap长度=100
i=30的结果数据为:resultList长度=100;resultMap长度=100
i=31的结果数据为:resultList长度=100;resultMap长度=100
i=32的结果数据为:resultList长度=100;resultMap长度=100
i=33的结果数据为:resultList长度=100;resultMap长度=100
i=34的结果数据为:resultList长度=100;resultMap长度=100
i=35的结果数据为:resultList长度=100;resultMap长度=100
i=36的结果数据为:resultList长度=100;resultMap长度=100
i=37的结果数据为:resultList长度=100;resultMap长度=100
i=38的结果数据为:resultList长度=100;resultMap长度=100
i=39的结果数据为:resultList长度=100;resultMap长度=100
i=40的结果数据为:resultList长度=100;resultMap长度=100
i=41的结果数据为:resultList长度=100;resultMap长度=100
i=42的结果数据为:resultList长度=100;resultMap长度=100
i=43的结果数据为:resultList长度=100;resultMap长度=100
i=44的结果数据为:resultList长度=100;resultMap长度=100
i=45的结果数据为:resultList长度=100;resultMap长度=100
i=46的结果数据为:resultList长度=100;resultMap长度=100
i=47的结果数据为:resultList长度=100;resultMap长度=100
i=48的结果数据为:resultList长度=100;resultMap长度=100
i=49的结果数据为:resultList长度=100;resultMap长度=100
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值