【Java8新特性】关于并行流与串行流,你必须掌握这些!!
写在前面
提到Java8,我们不得不说的就是Lambda表达式和Stream API。而在Java8中,对于并行流和串行流同样做了大量的优化。对于并行流和串行流的知识,也是在面试过程中,经常被问到的知识点。当然,我们不能只是为了应付面试来学习这些知识,更重要的是将这些知识运用到实际的工作中,更好的提高我们的工作效率和工作质量。
什么是并行流?
简单来说,并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。
Java 8 中将并行进行了优化,我们可以很容易的对数据进行并行操作。 Stream API 可以声明性地通过 parallel() 与sequential() 在并行流与顺序流之间进行切换 。
Fork/Join 框架
Fork/Join 框架: 就是在必要的情况下,将一个大任务,进行拆分(fork)成若干个小任务(拆到不可再拆时),再将一个个的小任务运算的结果进行 join 汇总 。
Fork/Join 框架与传统线程池有啥区别?
采用 “工作窃取”模式(work-stealing):
当执行新的任务时它可以将其拆分成更小的任务执行,并将小任务加到线程队列中,然后再从一个随机线程的队列中偷一个并把它放在自己的队列中。
相对于一般的线程池实现,fork/join框架的优势体现在对其中包含的任务的处理方式上。在一般的线程池中,如果一个线程正在执行的任务由于某些原因无法继续运行,那么该线程会处于等待状态。而在fork/join框架的实现中,如果某个子任务由于等待另外一个子任务的完成而无法继续运行。那么处理该子问题的线程会主动寻找其他尚未运行的子任务来执行。这种方式减少了线程的等待时间,提高了程序的性能。
Fork/Join框架实例
了解了ForJoin框架的原理之后,我们就来手动写一个使用Fork/Join框架实现累加和的示例程序,以帮助读者更好的理解Fork/Join框架。好了,不废话了,上代码,大家通过下面的代码好好体会下Fork/Join框架的强大。
package io.binghe.concurrency.example.aqs;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.Future;
import java.util.concurrent.RecursiveTask;
@Slf4j
public class ForkJoinTaskExample extends RecursiveTask<Integer> {
public static final int threshold = 2;
private int start;
private int end;
public ForkJoinTaskExample(int start, int end) {
this.start = start;
this.end = end;
}
@Override
protected Integer compute() {
int sum = 0;
//如果任务足够小就计算任务
boolean canCompute = (end - start) <= threshold;
if (canCompute) {
for (int i = start; i <= end; i++) {
sum += i;
}
} else {
// 如果任务大于阈值,就分裂成两个子任务计算
int middle = (start + end) / 2;
ForkJoinTaskExample leftTask = new ForkJoinTaskExample(start, middle);
ForkJoinTaskExample rightTask = new ForkJoinTaskExample(middle + 1, end);
// 执行子任务
leftTask.fork();
rightTask.fork();
// 等待任务执行结束合并其结果
int leftResult = leftTask.join();
int rightResult = rightTask.join();
// 合并子任务
sum = leftResult + rightResult;
}
return sum;
}
public static void main(String[] args) {
ForkJoinPool forkjoinPool = new ForkJoinPool();
//生成一个计算任务,计算1+2+3+4
ForkJoinTaskExample task = new ForkJoinTaskExample(1, 100);
//执行一个任务
Future<Integer> result = forkjoinPool.submit(task);
try {
log.info("result:{}", result.get());
} catch (Exception e) {
log.error("exception", e);
}
}
}
Java8中的并行流实例
Java8对并行流进行了大量的优化,并且在开发上也极大的简化了程序员的工作量,我们只需要使用类似如下的代码就可以使用Java8中的并行流来处理我们的数据。
LongStream.rangeClosed(0, 10000000L).parallel().reduce(0, Long::sum);
在Java8中如何优雅的切换并行流和串行流呢?
Stream API 可以声明性地通过 parallel() 与sequential() 在并行流与串行流之间进行切换 。
写在最后
如果觉得文章对你有点帮助,请微信搜索并关注「 冰河技术 」微信公众号,跟冰河学习Java8新特性。
最后,附上Java8新特性核心知识图,祝大家在学习Java8新特性时少走弯路。
【Java8新特性】关于并行流与串行流,你必须掌握这些!!的更多相关文章
- Java8的新特性--并行流与串行流
目录 写在前面 Fork/Join框架 Fork/Join框架与传统线程池的区别 传统的线程池 Fork/Join框架 Fork/Join框架的使用 Java8中的并行流 写在前面 我们都知道,在开发 ...
- JDK8--07:并行流与串行流
JDK8中,提供了并行流和串行流,使用parallel()和sequential()来处理,parallel()为并行流sequential()为串行流,两者可以相互转换,以最后一个为准 LongSt ...
- Java8新特性 并行流与串行流 Fork Join
并行流就是把一个内容分成多个数据块,并用不同的线程分 别处理每个数据块的流. Java 8 中将并行进行了优化,我们可以很容易的对数据进行并 行操作. Stream API 可以声明性地通过 para ...
- Java8新特性 - 并行流与串行流
并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流. Java8中将并行进行了优化,我们可以很容易的对数据进行并行操作.Stream API可以声明性地通过parallel()和 ...
- 三、并行流与串行流 Fork/Join框架
一.并行流概念: 并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流. java8中将并行进行了优化,我们可以很容易的对数据进行并行操作.Stream API可以声明性的通过pa ...
- java8新特性,使用流遍历集合
在这篇“Java 8新特性教程”系列文章中,我们会深入解释,并通过代码来展示,如何通过流来遍历集合,如何从集合和数组来创建流,以及怎么聚合流的值. 在之前的文章“遍历.过滤.处理集合及使用Lambda ...
- 2020你还不会Java8新特性?方法引用详解及Stream 流介绍和操作方式详解(三)
方法引用详解 方法引用: method reference 方法引用实际上是Lambda表达式的一种语法糖 我们可以将方法引用看作是一个「函数指针」,function pointer 方法引用共分为4 ...
- Java8 新特性 Stream() 创建流
通过Controllere类的Stream()和parallelStream()创建流 //通过集合创建流 @Test public void test1() { String arr[] = new ...
- 1.3 java8新特性总结
java8中重要的4个新特性: Lambda Stream Optional 日期时间API 接口方法(default和static方法,jdk9可定义private方法) 一.Lambda impo ...
随机推荐
- django+nginx+uwsgi的生产环境部署(Ubuntu16.04)
一,准备工作: 代码一定要能本地跑起来! 各种基础包的安装略默认已经安装python3,nginx,uwsgi等基础依赖,注意版本问题. 本地setting.py文件修改如下(改为生产模式,把debu ...
- awk调用date命令
创建文件date.awk: $ == { cmd = "\"" while (cmd | getline line) { print line } close(cmd) ...
- JavaScript 循环判断练习题
JavaScript 循环判断练习题 小明有一组水果("苹果","梨子","香蕉","葡萄","西瓜" ...
- 基本Linux命令(上)
Linux的难点在于我们需要记忆大量的命令及参数.如有问题请批评指正,在下感激不尽. Linux的命令都是在shell下使用的,也就是我们常说的终端(Terminal).包 ...
- Spring Cloud 学习 之 Spring Cloud Bus实现修改远程仓库后配置自动刷新
版本号: Spring Boot:2.1.3.RELEASE Spring Cloud:G版 开发工具:IDEA 搭建配置中心,这里我们搭建一个简单版的就行 POM: <?xml ...
- 视频文件自动转rtsp流
最近碰到一个项目需要用到 rtsp 视频流做测试, 由于真实环境的 摄像头 并不能满足需求,故尝试了一下用本地视频文件转换成rtsp视频流做测试,记录一下~ 采用方案: Docker + EasyDa ...
- Openwrt:基于MT7628/MT7688的PWM驱动
前言 MT7628/MT7688的PWM驱动相关资料较少,官方的datasheet基本也是一堆寄存器,啃了许久,终于嚼出了味道.由于PWM存在IO口复用的问题,所以要提前配置好GPIO的工作方式,不然 ...
- Jmeter-函数助手之${__RandomString(,,)}使用
${__RandomString(,,)}使用方法 1.在日常写脚本中,可以随机生成指定的几个字符串作为入参的value,那么jmeter 的这个工具就特别好用. 应用: 2.填写接口入参, 3.运 ...
- python 基础应用5-简单购物车
1.列表去重 #列表去重 li = [1,2,33,33,2,1,4,5,6,6] set1 = set(li)# 转为集合 li = list(set1)# 转为列表 print(li)#[1, 2 ...
- 关于python中第三方库安装方法和问题解决
一.安装方法 方法一: 1.管理员身份启动命令行(运行--->cmd) 2.pip install 库的绝对路径和库的详细名称 :或者运用cd命令跳转到下载好的库所在的位置然后pip insta ...