Java8 parallelStream 提升集合处理性能N(约等于CPU核数)倍

  • Stream(流)简介
  • parallelStream集合处理效率
      案例说明
      线程池(ForkJoinPool)
       分治法
       工作窃取算法
     注意事项
  • 总结思考
     优缺点
     parallelStream适用场景

Stream(流)简介

 Stream(流)是Java8新增对集合处理的抽象概念,类似于数据库结构化查询语句(SQL),使用Stream API 对集合数据进行操作,就类似于使用SQL执行的数据库查询。
 集合可以通过stream()方法创建串行流(元素一个接一个串行处理),parallelStream()方法创建并行流(多个元素可同时进行处理)。

parallelStream集合处理效率

案例说明

代码如下:

public class StreamTest {

    public static void main(String[] args) {
        System.out.println("CPU核数:num=" + Runtime.getRuntime().availableProcessors() + "
");
        List<Integer> list = IntStream.range(0,10).boxed().collect(Collectors.toList());

        long startTime = System.currentTimeMillis();
        System.out.println(list.stream().map(StreamTest::format).collect(Collectors.toList()));
        System.out.println("stream() time=" + (System.currentTimeMillis() - startTime) + "
");

        startTime = System.currentTimeMillis();
        System.out.println(list.parallelStream().map(StreamTest::format).collect(Collectors.toList()));
        System.out.println("parallelStream() time=" + (System.currentTimeMillis() - startTime));
    }

    public static Integer format(Integer i) {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName());
        return i+1;
    }
}

执行结果:

CPU核数:num=4

*** stream()方法数据串行执行,执行时间等于每个集合元素处理时间之和 ***
main
main
main
main
main
main
main
main
main
main
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
stream() time=1031

*** parallelStream()方法数据并行执行,执行时间约等于所有每个集合元素处理时间之后/CPU核数 ***
ForkJoinPool.commonPool-worker-1
main
ForkJoinPool.commonPool-worker-3
ForkJoinPool.commonPool-worker-2
ForkJoinPool.commonPool-worker-3
main
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-2
ForkJoinPool.commonPool-worker-3
main
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
parallelStream() time=312

说明:
1,parallelStream使用ForkJoinPool线程池处理任务
2,ForkJoinPool默认线程池大小为CPU核数-1(注:主线程也负责处理任务),不提议修改该大小

线程池(ForkJoinPool)

分治法

Java8 parallelStream 提升集合处理性能N(约等于CPU核数)倍

说明:
 Fork/Join框架的核心思想是采用分治法的思想。分治法:将一个复杂的问题拆分成若干个规模较小,相对独立但问题类型一样的子问题进行处理,然后再将子问题的结果合并成原始问题的完整答案。这样的问题处理策略就叫分治法。分治法三个关键步骤:1,问题拆分;2,子问题计算;3,合并。
采用分治法可以有效利用多核CPU的优势,把子问题通过并行计算,提高整体性能。

工作窃取算法

Java8 parallelStream 提升集合处理性能N(约等于CPU核数)倍

说明:
 工作窃取(work-stealing)算法是Fork/Join框架的核心理念,指当某个处理线程空闲后,为了合理利用CPU资源,就从其他线程的任务队列里面窃取任务来执行,这样能减少CPU空闲等待时间,提高空闲CPU的利用率。

注意事项

1,parallelStream()是线程不安全的
2,parallelStream()是以充分使用CPU资源来提升效率,不在多线程种使用
3,parallelStream()确保每个处理是无状态且没有关联的

总结思考

优缺点

优点

1,成倍提升集合处理效率,提高系统性能(TPS/QPS)

缺点

1,线程不安全,需要正确合理使用(解决方法:加锁、使用线程安全的集合或者采用collect()或者reduce()操作)

parallelStream适用场景

1,计算密集型集合处理(合理使用多核CPU的优势)


参考资料:https://www.jianshu.com/p/3d4e76467990

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容