for循环与串行化、并行化Stream流性能对比
并行流parallelStream注意事项 1、parallelStream是线程不安全的 2、parallelStream适用的场景是CPU密集型的,只是做到别浪费CPU,假如本身电脑CPU 的负载很大,那还到处用并行流,那并不能起到作用 3、I/O密集型 磁盘I/O、网络I/O都属于I/O操作,这部分操作是较少消耗CPU资源,一般并 行流中不适用于I/O密集型的操作,就比如使用并流行进行大批量的消息推送,涉及到了 大量I/O,使用并行流反而慢了很多 4、在使用并行流的时候是无法保证元素的顺序的,也就是即使你用了同步集合也只能保 证元素都正确但无法保证其中的顺序
解决并行流的线程安全问题:多线程下,使用并行流会有线程安全的问题 根据需要进行不同的处理: 1、使用同步代码块 synchronized (比如使用forEach循环处理时) 2、使用线程安全的集合 Vector、Collections.synchronizedList(list) 3、调用Stream流的 collect/toArray 方法
普通for循环、串行流、并行流在循环处理数据时性能对比:
测试代码:
public static void main(String[] args) { List<String> list = new ArrayList<>(); for(int i = 0; i < 15000000;i++){ list.add("a"+i); } StopWatch stopWatch = new StopWatch(); stopWatch.start(); for(int i = 0; i < list.size();i ++){ if(list.get(i).endsWith("0000000")){ System.out.println("END=================="); } } stopWatch.stop(); System.out.println("=====for===耗费:"+stopWatch.getTime()); stopWatch.reset(); stopWatch.start(); list.stream().filter(x -> x.endsWith("0000000")).forEach(a->{ System.out.println("END=================="); }); stopWatch.stop(); System.out.println("=====stream===耗费:"+stopWatch.getTime()); stopWatch.reset(); stopWatch.start(); list.parallelStream().filter(x -> x.endsWith("0000000")).forEach(a->{ System.out.println("END=================="); }); stopWatch.stop(); System.out.println("=====parallelStream===耗费:"+stopWatch.getTime()); }
总结: 修改上面代码数据量的大小结果不同, 可以看到,串行化流在数据量很小的情况下,性能最差。而并行化流则处于波动的状态。 所以单单从数据量上可以看出: for循环的性能随着数据量的增加性能也越来越差。 串行化流则在数据量小的情况下性能差,数据量中、大的时候性能略高于for循环,但当数据量特别大时,性能也变得越差。 并行化流受CPU核数的影响,在本机2核下,在数据量小的情况下性能略高于串行化流,略低于for循环,在数据量中的情况下差不多,在数据量比较大时性能最差,但当数据量特别大时,性能也变得更好。 如果想要使用parallelStream想提高性能,一定要根据实际情况做好测试,因为并行化的流性能不一定比串行化流性能高。