jdk1.8新特性-并行流和串行流

Posted by     "麦子" on Wednesday, 2019年07月03日

[TOC]

转载地址:https://blog.csdn.net/Keith003/article/details/80252553

转载地址:https://blog.csdn.net/caishi13202/article/details/82667230

并行流定义

并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。Java 8 中将并行进行了优化,我们可以很容易的对数据进行并行操作。Stream API 可以声明性地通过parallel() 与sequential() 在并行流与顺序流之间进行切换。

流可以是顺序的也可以是并行的。顺序流的操作是在单线程上执行的,而并行流的操作是在多线程上并发执行的。

Fork/Join 框架

Fork/Join 框架:就是在必要的情况下,将一个大任务,进行拆分(fork)成若干个小任务(拆到不可再拆时),再将一个个的小任务运算的结果进行join 汇总.

20180509141820711

Fork/Join 框架与传统线程池的区别

采用“工作窃取”模式(work-stealing): 当执行新的任务时它可以将其拆分分成更小的任务执行,并将小任务加到线程队列中,然后再从一个随机线程的队列中偷一个并把它放在自己的队列中。 相对于一般的线程池实现,fork/join框架的优势体现在对其中包含的任务的处理方式上.在一般的线程池中,如果一个线程正在执行的任务由于某些原因无法继续运行,那么该线程会处于等待状态.而在fork/join框架实现中,如果某个子问题由于等待另外一个子问题的完成而无法继续运行.那么处理该子问题的线程会主动寻找其他尚未运行的子问题来执行.这种方式减少了线程的等待时间,提高了性能.

工作窃取模式

ForkJoin框架采用的是“工作窃取模式”,传统线程在处理任务时,假设有一个大任务被分解成了20个小任务,并由四个线程A,B,C,D处理,理论上来讲一个线程处理5个任务,每个线程的任务都放在一个队列中,当B,C,D的任务都处理完了,而A因为某些原因阻塞在了第二个小任务上,那么B,C,D都需要等待A处理完成,此时A处理完第二个任务后还有三个任务需要处理,可想而知,这样CPU的利用率很低。而ForkJoin采取的模式是,当B,C,D都处理完了,而A还阻塞在第二个任务时,B会从A的任务队列的末尾偷取一个任务过来自己处理,C和D也会从A的任务队列的末尾偷一个任务,这样就相当于B,C,D额外帮A分担了一些任务,提高了CPU的利用率。

实例证明是否多线程

public static void main(String[] args) {   
   List<Integer> data=Arrays.asList(1,2,3,4,5,6,7);
   data.stream().forEach(System.out::println);

   System.out.println("-----------------------------");
  
   data.parallelStream().forEach(System.out::println);
  
   System.out.println("*****************************");
   /***
         * 如果forEachOrdered()中间有其他如filter()的中介操作,会试着平行化处理,然后最终forEachOrdered()会以原数据顺序处理,
         * 因此,使用forEachOrdered()这类的有序处理,可能会(或完全失去)失去平行化的一些优势,实际上中介操作亦有可能如此,例如sorted()方法。
    */
   data.parallelStream().forEachOrdered(System.out::println);
}
运行结果
1
2
3
4
5
6
7
-----------------------------
5
4
2
7
6
3
1
*****************************
1
2
3
4
5
6
7

stream和parallelStream方法中进行选择

转载地址:https://www.jianshu.com/p/9a11f41c2b63

是否需要并行?

你需要弄清楚你要解决的问题是什么,数据量有多大,计算的特点是什么?并不是所有的问题都适合使用并发程序来求解,比如当数据量不大时,顺序执行往往比并行执行更快。毕竟,准备线程池和其它相关资源也是需要时间的。但是,当任务涉及到I/O操作并且任务之间不互相依赖时,那么并行化就是一个不错的选择。通常而言,将这类程序并行化之后,执行速度会提升好几个等级。

任务之间是否是独立的?是否会引起任何竞态条件?

如果任务之间是独立的,并且代码中不涉及到对同一个对象的某个状态或者某个变量的更新操作,那么就表明代码是可以被并行化的。

结果是否取决于任务的调用顺序?

由于在并行环境中任务的执行顺序是不确定的,因此对于依赖于顺序的任务而言,并行化也许不能给出正确的结果。

「真诚赞赏,手留余香」

真诚赞赏,手留余香

使用微信扫描二维码完成支付