通过线程池方式改造Stream.parallel()并行流

Java 并行流(Parallel Stream)详解 并行流是Java 8引入的高效处理集合数据的工具,通过多线程加速计算。Fork/Joinparallel()mapfilterreduce并行操作中修改共享变量会导致线程安全问题,应使用无状态操作或同步控制。如sorted()distinct()在并行流中可能更耗时,需合并线程结果。ArrayListLinkedListTreeSet使用保证顺序,但牺牲性能。 阅读详情

在这里插入图片描述

大家好,我是哪吒。

上一篇简单聊一聊公平锁和非公平锁,parallel并行流,提到了一个IntStream.rangeClosed并行流问题,很多小伙伴,对这个比较陌生,想用线程池的方式改造一下。

一、IntStream.rangeClosed并行流

@Data
public class LockTest1 {
    public static void main(String[] args) {
        IntStream.rangeClosed(1, 100000).parallel().forEach(i -> new LockTest1().increase());
        System.out.println(time);
    }

    private static int time = 0;

    private static Object lock = new Object();
    public void increase() {
        synchronized (lock) {
            time++;
        }
    }
}

二、线程池方式改造

不会那些新特性,还是原始的香啊,写起代码,得心应手。

1、创建线程池

这时候,有些小伙伴,又陷入了选择恐惧症。用哪个线程池比较好呢?

简单回顾一下:

  1. 单线程池newSingleThreadExecutor(),只有一个核心线程的线程池,保证任务按FIFO顺序一个个执行;
  2. 固定线程数线程池newFixedThreadPool(10),固定数量的可复用的线程数,来执行任务。当线程数达到最大核心线程数,则加入队列等待有空闲线程时再执行;
  3. 可缓存线程池newCachedThreadPool(),创建的都是非核心线程,而且最大线程数为Interge的最大值,空闲线程存活时间是1分钟。如果有大量耗时的任务,则不适该创建方式,它只适用于生命周期短的任务;
  4. 固定线程数newScheduledThreadPool(10),支持定时和周期性任务newScheduledThreadPool(10),顾名思义,在固定线程数的前提下,添加了定时任务。

最常用的还是固定线程数线程池newFixedThreadPool(10)。

@Data
public class LockTest2 {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(200);
        for (int i = 0; i < 100000; i++) {
            Thread0926 thread = new Thread0926();
            executorService.execute(thread);
        }
        System.out.println(time);
    }

    private static int time = 0;
    private static Object lock = new Object();
    public void increase() {
        synchronized (lock) {
            time++;
        }
    }
}

2、线程类

public class Thread0926 implements Runnable{
    @Override
    public void run() {
        LockTest2 lockTest = new LockTest2();
        lockTest.increase();
    }
}

3、信心满满,走起来

我草,这不对啊,不应该是100000嘛?又把老子整不会了~

在这里插入图片描述

三、再次解决并发时i++原子性问题

上一篇测试过,使用synchronized代码块是可以解决i++线程安全问题的,这次怎么不好使了?

上面的代码中,synchronized (lock)锁住了time++,lock是静态变量,所以属于类级别的锁。但是新建的线程是一个新的类,超出了锁的范围,所以失效。

那么,在当前类中,开启线程,是不是就可以了呢?试一下

public class LockTest4 {
    private static int time = 0;
    private static Object lock = new Object();
    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 200; i++) {
            Thread thread = new Thread(() -> {
                for (int j = 0; j < 500; j++) {
                    synchronized (lock) {
                        time++;
                    }
                }
            });
            thread.start();
        }
        Thread.sleep(3000);
        System.out.println(time);
    }
}

当然,在synchronized代码块中,使用synchronized (LockTest4.class)也是可以的,效果是一样的。

在这里插入图片描述

四、并行流与多线程

并行流的本质的是并行,多线程的本质是并发。

并行指当多核CPU中的一个CPU执行一个线程时,其它CPU能够同时执行另一个线程,两个线程之间不会抢占CPU资源,可以同时运行。

并发指在一段时间内CPU处理多个线程,这些线程会抢占CPU资源,CPU资源根据时间片周期在多个线程之间来回切换,多个线程在一段时间内同时运行,而在同一时刻不是同时运行的。

1、并行和并发的区别?

  1. 并行指多个线程在一段时间的每个时刻都同时运行,并发指多个线程在一段时间内同时运行(不是同一时刻,一段时间内交叉执行)
  2. 并行的多个线程不会抢占系统资源,并发的多个线程会抢占系统资源;
  3. 并行是多CPU的产物,单核CPU中只有并发,没有并行;

在这里插入图片描述

2、并行和并发的使用场景

(1)IO密集场景

场景应用程序开发,提供http接口、数据库查询、微服务调用都是IO请求,IO请求时几乎不消耗cpu,这是为了提供cup使用率,建议使用多线程并发,线程数可以远大于cpu核数。

(2)cup密集场景

对应大量的加减乘除运算、md5、hash等运算操作,需要持续使用cpu,需要让多核cpu并行运算,适合使用forkjoin并行计算。

技术场景多线程不足,使用多线程技术,也能提高性能,但是线程设置过大会浪费cpu线程切换的时间,如果线程任务分配不均匀,会导致有的cpu忙碌有的cpu空闲。

上一篇:一个关于 i++ 和 ++i 的面试题打趴了所有人

下一篇:越细粒度的锁越好吗?产生死锁怎么办?

🏆哪吒多年工作总结:Java学习路线总结,搬砖工逆袭Java架构师。

Stream.parallel()对流的并行处理 Stream.parallel()一种简单且强大的并发方式。当然,最好的并发就是不并发。 阅读详情

相关推荐

JAVA:Stream 并行(parallel)详解及优化实践

Java 8 的 Stream API 提供了并行处理能力,通过 parallel() 或 parallelStream() 可利用多核 CPU 提升性能。但使用不当会导致线程安全、性能下降等问题。本文解析了并行流的工作原理(基于 ForkJoinPool)、常见陷阱(如非线程安全操作、小数据量开销大)及优化方案:确保线程安全、大数据量适用、使用 unordered() 提升效率、自定义线程池控制并发等。建议 CPU 密集型大数据任务使用并行流,而 IO 密集型或小数据量场景慎用,并通过性能测试验证效果。

木头 818

Java Stream对象并行处理方法parallel()

通常情况下,Stream API上的大多数操作都是顺序执行的,也就是说操作一个元素,然后再操作下一个元素。需要注意的是,并行计算不一定总是比串行计算更快,因为创建线程以及进行线程间通信的开销也是很大的。同时,在使用并行流时,需要确保Stream的操作是无状态或者线程安全的,否则可能会导致意外的结果。具体来说,Stream的parallel()方法可以将一个顺序流转换为一个并行流。使用并行流时,不需要手动设置线程数,因为Java会自动根据CPU核心数瓶颈以及程序的处理需求设置最优的线程数。

Ascend1977的博客 9632

华为2022硬件逻辑笔试题

单选题(每题两分) 1.以下关于过程赋值的描述,不正确的是() A在非阻塞性过程赋值中,使用赋值符号“< =” B赋值操作符是“=”的过程赋值是阻塞性过程赋值 C在非阻塞性过程赋值中,对目标的赋值是非阻塞的(因为时延),但可预定在将来某个时间步发生(根据时延:如果是0时延,那么在当前时间步结束) D非阻塞性过程赋值在其后所有语句执行前执行 解:D 2.芯片的功耗和下列哪种不强相关_____________。 A资源利用率 B核电压 C组合逻辑级数 D翻转率 解:A 3.下列说

weixin_44072819的博客 1万+

Java8--Stream 并行流详解

简介 并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。串行流则相反,并行流的底层其实就是ForkJoin框架的一个实现。 java.util.Collection &lt; E &gt;新添加了两个默认方法 default Stream stream() : 返回串行流 default Stream parallelStream() : 返回并行流 将一个并行流转成顺...

惜阳 1万+

中国30米逐年植被净初级生产力(NPP)数据集(1982年至今CASA模型)

1.3 气温、降水、地表太阳辐射数据 气温和降水数据月度空间插值数据是基于全国2400多个站点的日观测数据,在计算各气象要素月值的基础上,基于Anusplin软件插值生成的1982年以来各月度30米分辨率气温和降水栅格数据,插值过程中引入高程作为协变量。气温单位为℃,降水单位为mm。1.2 土地覆盖数据 土地覆盖数据来源于1985 年-2020年全球30米精细地表覆盖动态监测产品,该数据集包含29个地表覆盖类型,进行拼接、裁剪、重分类和重采样处理,获得8期250米分辨率的植被类型数据。

地球资源数据云的官方博客 2840

matlab生成blocks、bumps和doppler标准测试信号

关键函数:wnoise使用方式X = wnoise(FUN,N) [X,XN] = wnoise(FUN,N,SQRT_SNR) [X,XN] = wnoise(FUN,N,SQRT_SNR,INIT)X = wnoise(FUN,N) 返回由 FUN给出的信号,长度为2^N,幅值范围[0,1].[X,XN] = wnoise(FUN,N,SQRT_SNR) ,返回了一个测试信号X,以及一个加噪

ZSZ_shsf的博客 6582

Java并行流Parallel Stream与Fork-Join线程池

Fork-Join Parallel Stream实现任务的切分,并将任务提交到全局的ForkJoinPool线程池中执行,注意,是全局的线程池。关于ForkJoinPool,我这里简单介绍下。 在Fork-Join中,比如一个拥有4个线程的ForkJoinPool线程池,有一个任务队列,一个大的任务切分出的子任务会提交到线程池的任务队列中,4个线程从任务队列中获取任务执行,哪个线程执行的任务快,哪个线程执行的任务就多,只有队列中没有任务线程才是空闲的,这就是工作窃取。可以这样理解工作窃取,比如有4个人干

njitzyd 5358

RK356x U-Boot研究所(命令篇)3.7 pci与nvme命令的用法

RK356x U-Boot研究所(命令篇)3.7 pci与nvme命令的用法

Systemcall名屋 2084

【java8】并行流Stream

流在处理数据进行一些迭代操作的时候确认很方便,但是在执行一些耗时或是占用资源很高的任务时候,串行化的流无法带来速度/性能上的提升,并不能满足我们的需要。通常我们会使用多线程来并行或是分片分解执行任务,而在Stream中也提供了这样的并行方法,下面将会一一介绍这些方法。使用parallelStream()方法或者是使用stream().parallel()来转化为并行流。但是只是可能会返回一个并行的流,流是否能并行执行还受到其他一些条件的约束(如是否有序,是否支持并行)。对顺序流调用parallel方法并不意

morris 4205

华为OD机试双机位C卷-热点网站统计 (Py/Java/C/C++/Js/Go)

华为OD机试双机位C卷 热点网站统计,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解。 华为od机考真题 - 热点网站统计。

qq_45776114的博客 779

mongodb在游戏开发领域的优势

目前游戏服务器使用mysql作为数据库的较多,然而,使用mongodb来作为存储层,在某些方面比mysql更为方便和适合。

littleschemer的博客 1700

并行流parallel,CompletableFuture与Executors线程池的使用与区别

list并行操作在项目开发可以极大提高代码效率与性能,java8对其进行了很好的封装,简单使用研究一下: 1. 先自己创建一个list: // list在实际使用中要注意线程安全,Collections.synchronizedList写操作性能高,CopyOnWriteArrayList读操作性能较好 List<String> list = Arrays.asList(new String[10000]); 2. parallel并行流使用: list.stream().paral

z69183787的专栏 4303

重回童年的经典系列☀️|【炸弹人小游戏】制作过程+解析 | 收藏起来跟曾经的小伙伴一起梦回童年!

Unity,小游戏开发。 本篇文章对童年经典小游戏——炸弹超人进行制作和解析。不知道有没有勾起你童年的回忆呢!快来和我一起制作这个童年经典的小游戏吧! 敬请品尝!

努力前行,总会成为自己心中的那道光 13万+

大聪明教你学Java | 深入浅出聊 Stream.parallel()

相信各位小伙伴对 Stream 都不陌生,它是 Java 8 及以后版本中引入的一个新特性,用于处理集合数据。Stream 是对集合(Collection)对象功能的增强,与 Lambda 表达式结合,可以提高编程效率、间接性和程序可读性。Stream API 中为我们提供了很多高效且易用的方法,大聪明的好朋友 —— 大明白就对这些方法情有独钟,但是就在前几天,却因为他在项目中使用了 Stream.parallel() 而引发了一个小小的意外情况... ...

不肯过江东丶 1335

【ESP32接入国产大模型之Deepseek】

🥳🥳🥳现在,我们在本教程中,您学习了如何使用ESP32接入语言大模型之Deepseek。🛹🛹🛹从而实现对外部世界进行感知,充分认识这个有机与无机的环境,后期会持续分享esp32跑freertos实用案列🥳🥳🥳科学地合理地进行创作和发挥效益,然后为人类社会发展贡献一点微薄之力。🤣🤣🤣如果你有任何问题,可以通过q group(945348278)加入鹏鹏小分队,期待与你思维的碰撞😘😘😘鸣谢B站UP星汇极客ESP32对接DeepSeek API,实现AI大模型交互功能。

vor234的博客 1万+

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

强大的Stream API以及并行流与串行流

文章目录Stream APIStreamStream操作的三个步骤创建Stream中间操作终止操作创建StreamStream的中间操作筛选与切片映射排序Stream的终止操作查找与匹配归约收集并行流与串行流了解Fork/Join框架Fork/Join框架与传统线程池的区别 Stream API Stream是Java8中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的...

Debug Dog 4256

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Java 8并行流中的自定义线程池

Is it possible to specify a custom thread pool for Java 8 parallel stream ? 是否可以为Java 8 并行流指定自定义线程池

w36680130的博客 2291

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

并行流parallel 和 parallelStream

是 Java8 中的一个方法,可用于对一个 Stream 进行并行计算,该方法使得 Stream 中的元素在多个线程中被处理。是 Stream 接口的一个方法,它返回一个并行流,也可以用于对一个 Stream 进行并行计算。两者的区别在于,parallel 是在一个已经存在的串行 Stream 上调用的方法,而 parallelStream 是返回一个新的并行流。因此,parallelStream 在一些情况下可能更加方便,因为它可以避免在多个方法之间传递 Stream 对象。

qq_44086060的博客 2284

Java8 Stream 并行 parallel()

VisualVM 监控 public static void main(String[] args) { Thread thread=new Thread(()-> { Arrays.asList(1, 2, 3, 4, 5, 6, 7, 9, 8, 0, 1) .stream() .parallel() .collect(C

qq_25004825的博客 1万+

深入理解Java中的并行流(Parallel Stream)

并行流是Stream API的一种特殊实现,它通过拆分数据源,将多个任务分配给不同的线程并行执行,从而加速数据处理。并行流利用了多核处理器的优势,通过分治策略(divide-and-conquer)和Fork/Join框架,显著提高了处理大规模数据的效率。

weixin_53840353的博客 1372

Java8 Stream.parallel底层用的是哪个线程池?

调用stream最终循环的时候都会走AbstractPipeline的这个方法 final <R> R evaluate(TerminalOp<E_OUT, R> terminalOp) { assert getOutputShape() == terminalOp.inputShape(); if (linkedOrConsumed)...

tjouyang的博客 1132

Stream API中的并行流

什么是并行流 并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。 Java 8 中将并行进行了优化,我们可以很容易的对数据进行并行操作。Stream API 可以声明性地通过 parallel() 与sequential() 在并行流与顺序流之间进行切换。 在大数据操作中 肯定是并行流操作很快,能够最大限度的利用cpu资源 Fork/Join 框架 Fork/Join 框架:就是在必要的情况下,将一个大任务,进行拆分(fork)成若干个小任务(拆到不可再拆时),再将一个个的小任务运算

weixin_45844836的博客 448

如何用Parallel Collectors突破Java标准并行流限制?5分钟入门指南

Parallel Collectors是一个Java工具包,它通过Stream API简化并行集合处理,帮助开发者克服Java标准并行流的限制。无论是处理I/O密集型任务还是结构化工作负载,它都能提供更灵活、高效的并行处理能力,让你的Java应用性能得到显著提升。 ## 为什么需要Parallel Collectors? Java标准并行流(`parallelStream()`)虽然提供了并行

gitblog_01180的博客 1026

《Java8实战》读书笔记06:Parallel Stream 并行流

《Java8实战》 - 读书笔记 - Parallel Stream并行流知识第7章 并行数据处理与性能7.1 并行流7.1.1 将顺序流转换为并行流7.1.2 测量流性能7.1.3 正确使用并行流7.1.4 高效使用并行流7.2 分支/合并框架7.2.1 使用 RecursiveTask7.2.2 使用分支/合并框架的最佳做法 第7章 并行数据处理与性能 7.1 并行流 7.1.1 将顺序流转换为并行流 parallel sequential stream.parallel() .filter(.

灵台方寸山斜月三星洞 2335

java 8 stream_Java并行流Parallel Stream与ForkJoin线程池的关系,莫要乱用、滥用并行流...

在说stream之前,给大家分享一个数组匹配性能优化技巧,其实平时注意一些编码的优化,对整个系统的性能优化是有很大帮助的,积少成多。往往一个项目都是毁在一行行粗心代码上的,比如这里多占点内存,那里多占点内存,慢慢内存就不够用了,结果就想着升级机器配置。下面给出的代码例子就是判断一个整数是否在数组中,实际项目中数组是无序的。如果用List的contains方法,其实就是数组遍历。从输出结果...

weixin_39622587的博客 1070
上一篇: 华为OD机试 - 最大括号深度 - 栈stack(Java 2025 C卷 100分)
下一篇: 华为OD机试 - 用连续自然数之和来表达整数 - 滑动窗口(Java 2025 C卷 100分)
哪 吒
哪 吒 2022年度博客之星TOP 1 2022年度博客之星TOP 1 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄9年 59万+粉丝 2953原创
评论 13
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哪 吒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值