【JDK8新特性之Stream流-并行的Stream流以及案例实操】

news2024/10/2 14:29:47

一.JDK8新特性之Stream流-并行的Stream流以及案例实操

在这里插入图片描述

二. 并行的Stream流

2.1 串行的Stream流

我们前面使用的Stream流都是串行,也就是在一个线程上面执行。

/**
     * 串行流
     */
    @Test
    public void test01(){
        long count = Stream.of(1, 2, 3, 4, 5, 6)
                .filter(s -> {
                    System.out.println(Thread.currentThread() + "" + s);
                    return s % 2 == 0;
                }).count();
        System.out.println(count);
    }

结果输出

在这里插入图片描述

2.2 并行流

parallelStream其实就是一个并行执行的流,它通过默认的ForkJoinPool,可以提高多线程任务的速度。

2.2.1 获取并行流俩种方式

我们可以通过两种方式来获取并行流。

  1. 通过List接口中的parallelStream方法来获取
  2. 通过已有的串行流转换为并行流(parallel)
    /**
     * 获取并行流的两种方式
     */
    @Test
    public void test02(){
        List<Integer> list = new ArrayList<>();
        // 方式1:通过List接口中的parallelStream方法来获取
        Stream<Integer> integerStream = list.parallelStream();
        // 方式2:通过已有的串行流转换为并行流(parallel)
        Stream<Integer> parallel = Stream.of(1, 3).parallel();
    }

2.2.2 并行流操作

/**
     * 并行流操作
     */
    @Test
    public void test03(){

        long count = Stream.of(1, 2, 3, 4, 5, 6)
                .parallel() // 将流转换为并发流,Stream处理的时候就会通过多线程处理
                .filter(s -> {
                    System.out.println(Thread.currentThread() + "" + s);
                    return s % 2 == 0;
                }).count();
        System.out.println(count);
    }

结果展示

在这里插入图片描述

2.3 并行流和串行流对比

我们通过for循环,串行Stream流,并行Stream流来对10000000亿个数字求和。来看消耗时间

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.stream.LongStream;

public class Test03 {

    private static long times = 300000000;

    private long start;

    /**
     * 程序开始的时候获取当前系统的时间
     */
    @Before
    public void before(){
        start = System.currentTimeMillis();
    }

    /**
     * 程序结束的时候获取此时系统的时间
     * 计算消耗的时间
     */
    @After
    public void end(){
        long end = System.currentTimeMillis();
        System.out.println("消耗时间:" + (end - start));
    }


    /**
     * 串行流处理:消耗时间:271
     */
    @Test
    public void test02(){
        System.out.println("串行流处理:");
        LongStream.rangeClosed(0,times)
                .reduce(0,Long::sum);
    }

    /**
     * 并行流处理 消耗时间:158
     */
    @Test
    public void test03(){
        System.out.println("并行流处理:");
        LongStream.rangeClosed(0,times)
                .parallel()
                .reduce(0,Long::sum);
    }
}

通过案例我们可以看到parallelStream的效率是最高的。
Stream并行处理的过程会分而治之,也就是将一个大的任务切分成了多个小任务,这表示每个任务都是一个线程操作。
为什么呢?
因为它使用的线程池就是通过分而治之的思想实现的。

2.4 线程安全问题

在多线程的处理下,肯定会出现数据安全问题。如下:

    @Test
    public void test01(){
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 1000; i++) {
            list.add(i);
        }
        List<Integer> listNew = new ArrayList<>();
        // 使用并行流来向集合中添加数据
        list.parallelStream()
                .forEach(listNew::add);
        System.out.println(listNew.size());
    }

运行效果:

在这里插入图片描述

2.5 解决线程安全问题的三种方案

2.5.1 加同步锁

    /**
     * 加同步锁
     */
    @Test
    public void test01(){
        List<Integer> listNew = new ArrayList<>();
        Object obj = new Object();
        IntStream.rangeClosed(1,1000)
                .parallel()
                .forEach(i->{
                    synchronized (obj){
                        listNew.add(i);
                    }

                });
        System.out.println(listNew.size());
    }

2.5.2 使用线程安全的容器

  1. 使用线程安全的容器+synchronized
  2. 将线程不安全的容器转换为线程安全的容器

    /**
     * 使用线程安全的容器
     */
    @Test
    public void test02(){
        Vector v = new Vector();
        Object obj = new Object();
        IntStream.rangeClosed(1,1000)
                .parallel()
                .forEach(i->{
                    synchronized (obj){
                        v.add(i);
                    }

                });
        System.out.println(v.size());
    }

    /**
     * 将线程不安全的容器转换为线程安全的容器
     */
    @Test
    public void test03(){
        List<Integer> listNew = new ArrayList<>();
        // 将线程不安全的容器包装为线程安全的容器
        List<Integer> synchronizedList = Collections.synchronizedList(listNew);
        Object obj = new Object();
        IntStream.rangeClosed(1,1000)
                .parallel()
                .forEach(i->{
                        synchronizedList.add(i);
                });
        System.out.println(synchronizedList.size());
    }

2.5.3 通过Stream中的toArray/collect操作

通过Stream中的 toArray方法或者 collect方法来操作满足线程安全的要求

    @Test
    public void test05(){
        List<Integer> listNew = new ArrayList<>();
        Object obj = new Object();
        List<Integer> list = IntStream.rangeClosed(1, 1000)
                .parallel()
                .boxed()
                .collect(Collectors.toList());
        System.out.println(list.size());
    }

三.总结

我就是普普通通的一名从农村里走出来的孩子,我就是不信命,我相信凭借我我自己的努力可以让父母过上更好的生活!我们一起加油!!!冲鸭!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/369790.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux内核段页式内存管理技术

一、概述 1.虚拟地址空间 内存是通过指针寻址的&#xff0c;因而CPU的字长决定了CPU所能管理的地址空间的大小&#xff0c;该地址空间就被称为虚拟地址空间&#xff0c;因此32位CPU的虚拟地址空间大小为4G&#xff0c;这和实际的物理内存数量无关。 Linux内核将虚拟地址空间分…

Calendar计算两个时间之间相差几个月

目录说明说明 计算两个时间之间相差几个月&#xff1a; public int getMonth(String startDt, String endDt) { int month 0;try {SimpleDateFormat sdf new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");Calendar satrt Calendar.getInstance();Calendar end Cal…

有限差分法求解不可压NS方程

网上关于有限差分法解NS方程的程序实现不尽完备&#xff0c;这里是一些补充注解 现有的优秀资料 理论向 【1】如何从物理意义上理解NS方程&#xff1f; - 知乎 【2】NS方程数值解法&#xff1a;投影法的简单应用 - 知乎 【3】[计算流体力学] NS 方程的速度压力法差分格式_…

股票量化交易SQL特征工程入门

虽然现在各种量化教程和自助平台铺天盖地&#xff0c;但是对于新人来说入门最重要的事情就是挖掘特征。 对于传统的学习路径第一步是学习Python或者某一门编程语言&#xff0c;虽说Python入门容易上手快&#xff0c;但是要在实际应用中对股票数据进行分析&#xff0c;并挖掘有…

【数据库】第一章 绪论

第一章 绪论 1.1 数据库系统概述 数据库课程的学习内容 数据库的4个基本概念&#xff1a; 数据&#xff1a;描述事物的符号记录称为数据。 数据的含义成为数据的语义&#xff0c;数据与其语义是不可分割的。 数据库&#xff1a;数据库是长期存储在计算机内、有组织、可共享的…

Netty核心组件ChannelPipeline事件handler源码解析

源码解析目标 当请求进来&#xff0c;ChannelPipeline如何协调内部这些Handler通过源码梳理ChannelPipeline 与ChannelHandlerContext中的read&#xff0c;fireChannelRead等方法的不同 inbound源码解析 在 Netty启动流程源码剖析 文中我们已经知道&#xff0c;启动后&#…

公司项目vue cli2升级到vue cli3

背景&#xff1a;公司项目历时时间较长&#xff0c;通过长时间的迭代&#xff0c;目前项目文件较多&#xff08;src目录下有2217个文件&#xff09;&#xff0c;系统庞大&#xff0c; 之前通过vue cli2脚手架构建的项目框架&#xff0c;在本地开发时已经明显感觉到吃力&#xf…

Win10+vs2019配置与运行RenderMatch(踩坑记录)

Win10vs2019配置与运行RenderMatch RenderMatch旨在解决aerial images 和ground images 匹配问题&#xff0c;其思路可参考原论文 “Leveraging Photogrammetric Mesh Models for Aerial-Ground Feature Point Matching Toward Integrated 3D Reconstruction” 1.源码下载 G…

【2023new】OAK相机如何将Yolov5转换成blob格式?

编辑&#xff1a;OAK中国 首发&#xff1a;oakchina.cn 喜欢的话&#xff0c;请多多&#x1f44d;⭐️✍ 内容可能会不定期更新&#xff0c;官网内容都是最新的&#xff0c;请查看首发地址链接。 ▌前言 Hello&#xff0c;大家好&#xff0c;这里是OAK中国&#xff0c;我是助手…

机械革命极光Pro电脑开启出现英文代码无法启动怎么办?

机械革命极光Pro电脑开启出现英文代码无法启动怎么办&#xff1f;有的小伙伴在使用机械革命极光Pro电脑的时候&#xff0c;正常开启电脑却无法进入到桌面中&#xff0c;而是显示一些英文错误提示。遇到这个问题是我们的系统故障了&#xff0c;可以通过U盘重装系统的方法来进行问…

logback 自定义日志输出到数据库

项目日志格式 Spring Boot 的默认日志输出类似于以下示例&#xff1a; 2021-12-14 22:40:14.159 INFO 20132 --- [ main] com.kuangstudy.SpringbootApplication : Started SpringbootApplication in 2.466 seconds (JVM running for 3.617)输出以下项目&…

SpringBoot 整合 MongoDB 6 以上版本副本集及配置 SSL / TLS 协议

续上一篇 Linux 中使用 docker-compose 部署 MongoDB 6 以上版本副本集及配置 SSL / TLS 协议 前提&#xff1a;此篇文章是对上一篇文章的实战和项目中相关配置的使用&#xff0c;我这边针对 MongoDB 原有基础上做了增强&#xff0c;简化了 MongoDB 配置 SSL / TLS 协议上的支…

Android Studio引入JNI第三方库

一、前言 JNI作为Java与native沟通的桥梁&#xff0c;项目开发中难免要使用到&#xff1b;而我们除了自己开发JNI之外&#xff0c;有时候还要在Android Studio引入别人开源的C第三方库&#xff0c;并在jni层实现第三方库的调用。 二、流程 1.导入头文件和实现文件 将第三方…

Linux内核进程地址空间与进程内存布局

一&#xff0c;进程空间分布概述 对于一个进程&#xff0c;其空间分布如下图所示&#xff1a; 程序段(Text):程序代码在内存中的映射&#xff0c;存放函数体的二进制代码。初始化过的数据(Data):在程序运行初已经对变量进行初始化的数据。未初始化过的数据(BSS):在程序运行初未…

九龙证券|券商春季策略扎堆来袭 风格切换成焦点

2月以来&#xff0c;国泰君安、中信建投、国金证券等10余家券商组织相继发布2023年春季战略。综合来看&#xff0c;组织对A股持达观预期&#xff0c;未来两三个月A股商场或迎来重要切换。风格上&#xff0c;“中心财物&#xff0c;生长接力”或许成为上半年装备主线&#xff0c…

java 系列之Mybatis

java 系列文章 文章目录java 系列文章前言一、Mybatis 入门1.1 认识 框架&#xff08;了解&#xff09;1.2 认识 ORM&#xff08;要知道&#xff09;1.3 认识 Mybatis&#xff08;要知道&#xff09;二、Mybatis 使用2.1 创建maven项目并导入依赖2.2 准备数据库&#xff0c;包和…

释放内存流程

你好&#xff0c;我是安然无虞。 thread cache回收内存 当从 thread cache 中申请的内存对象使用完毕需要还回来的时候, 只需要计算出该内存对象对应 thread cache 中的哪一个自由链表桶, 然后将该内存对象插入进去即可. 不过需要注意的是, 如果不断有内存对象释放回来, 那么…

Java实现根据拼音首字母的排序

1.项目 手机APP端要对企业列表按企业名称首字母(如果企业名是英文的就按)进行分类排序&#xff0c;效果如下&#xff1a; 2.实现过程 2.1 首先引入项目的pinyin4j-2.5.0.jar包。 这个jar的下载地址如下&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1hkP_gGAYcgzyK_D…

跨链桥:Web3黑客必争之地

跨链桥&#xff0c;区块链的基础设施之一&#xff0c;所实现的功能是允许用户将自己的资产从一条链转移至另外一条链上&#xff0c;是连接不同的区块链的关键桥梁&#xff0c;常使用中心化的方式进行实现。由于跨链桥自身往往存储有用户所质押的巨额资产&#xff0c;是Web3黑客…

KUKA KR C4机器人与S7-1200PLC进行PROFINET通信的具体方法和步骤

KUKA KR C4机器人与S7-1200PLC进行PROFINET通信的具体方法和步骤 首先,从KUKA机器人控制柜中将KOP备选软件包拷贝出来,然后在“WorkVisual Development Environment”安装KUKA备选软件包(版本非常重要,尽量从控制柜中拷贝), 也可以从以下链接中获取: KUKA机器人PROFINET…