Java8踩坑指南1-parallelstream

           最近,在项目中使用了Java8中的stream,对它爱不释手,感觉对一些集合的操作可以变得如此简单,简直就是神器啊,对List,Set,Map可以很简单的进行相互转换,其中就用到了parallelstream,简单来说,它是一种并发执行的流,通过默认的ForkJoinPool,可以直接使用多线程进行处理,而对于开发者则不用关心细节,直接使用即可。
            虽然parallelstream功能很强大,但在使用的时候需要注意很多细节,先说一个容易忽略的点,以遍历List为例。首先,先说一下使用parallelstream的场景,我们去循环遍历List的时候可以使用forEach方法即可,或者使用while和for循环,但是在两种情况下可以考虑使用parallelstream,第一,当list中的元素数量很多时,使用parallelstream会体现出多线程的优势,多个线程同时处理元素会比单循环处理快很多(不绝对,取决于循环中的具体操作,如果有运算,一般会体现出优势),第二,list元素不是很多,但是每个循环中的操作都比较耗时,如果不使用多线程,相当于串行处理,处理速度必然要慢很多,这时候应当考虑使用parallelstream来提高处理速度。注意,这时候坑就出现了,当使用parallelstream时,如果使用了forEach时,元素的顺序就可能发生变化了,当然提供了forEachOrdered方法,但是我试了下,效率比较低,不推荐使用。使用简化的代码说明下,

public void main() throws Exception {
        List list = Arrays.asList(1, 2, 4, 5, 6, 3, 2, 4, 32, 2, 3242, 2, 3212, 2);
        long start = System.currentTimeMillis();
        list.forEach(i -> {
            //耗时操作
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            
        });
        System.out.println((System.currentTimeMillis() - start) + "ms");
        start = System.currentTimeMillis();
        list.parallelStream().forEach(i -> {
            //耗时操作
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        System.out.println((System.currentTimeMillis() - start) + "ms");
    }

执行结果:

可以看出,处理速度相差大概4倍左右,但是使用了parallelstream次序是乱的,如果对次序没有啥特殊要求的时候,这种场景下使用parallelstream效果还是非常明显的,我项目中就是因为第二种场景,需要查询一些数据拼接成list,然后在对list做遍历,每个循环又需要调用很多第三方的接口,虽然有分页每页20条,但是接口的响应时间还是很慢,在优化前,接口的调用时间大概在500ms左右,还算是比较高的,在处理之前就考虑的使用并发调用,所以使用了parallelstream来处理,虽然接口查询速度提升了,但是因为忽略的次序的问题,所以出现了查询出来的结果都是乱的,为了保证顺序就额外使用了HashMap存储数据,然后在循环list从map中get数据,虽保证数据有序性,但是却忽略了一个很低级的问题,HashMap是非线程安全的啊!这个坑踩的有点。。。结果导致产生了很多null的数据,就是因为多线程在操作HashMap时,会在resize的时候将链表的head指向了null,导致在get操作时,取出为null元素。随后使用了ConcurrentHashMap才将问题搞定,但是具体的问题还是要具体分析。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值