Java之并行流(Parallel Stream)使用詳解
Java并行流(Parallel Stream)
并行流是Java 8引入的高效處理集合數(shù)據(jù)的工具,通過(guò)多線程加速計(jì)算。
以下是其核心概念、使用方法及注意事項(xiàng)的詳細(xì)指南:
1. 核心概念與原理
- 并行處理機(jī)制:將數(shù)據(jù)分割為多個(gè)塊,利用
Fork/Join框架在多個(gè)線程上并行處理,最后合并結(jié)果。 - 默認(rèn)線程池:使用
ForkJoinPool.commonPool(),線程數(shù)等于CPU核心數(shù)(可通過(guò)系統(tǒng)參數(shù)調(diào)整)。 - 適用場(chǎng)景:大規(guī)模數(shù)據(jù)集、計(jì)算密集型任務(wù)(如數(shù)學(xué)運(yùn)算、批量轉(zhuǎn)換)。
2. 創(chuàng)建并行流的方式
- 直接生成:通過(guò)集合的
parallelStream()方法。 - 轉(zhuǎn)換順序流:在現(xiàn)有流上調(diào)用
parallel()。
List<Integer> list = Arrays.asList(1, 2, 3, 4); // 方式1:直接生成并行流 Stream<Integer> parallelStream1 = list.parallelStream(); // 方式2:將順序流轉(zhuǎn)為并行 Stream<Integer> parallelStream2 = list.stream().parallel();
3. 適用場(chǎng)景與性能優(yōu)化
推薦場(chǎng)景:
- 數(shù)據(jù)量大:如百萬(wàn)級(jí)元素的過(guò)濾、映射。
- 計(jì)算復(fù)雜:如矩陣運(yùn)算、圖像處理。
- 無(wú)狀態(tài)操作:如
map、filter、reduce(不依賴處理順序或外部變量)。
性能陷阱:
- 小數(shù)據(jù)集:并行化開(kāi)銷(線程調(diào)度、數(shù)據(jù)分割)可能抵消收益。
- 低耗時(shí)操作:如簡(jiǎn)單加減法,并行可能更慢。
4. 注意事項(xiàng)與最佳實(shí)踐
避免共享可變狀態(tài)
并行操作中修改共享變量會(huì)導(dǎo)致線程安全問(wèn)題,應(yīng)使用無(wú)狀態(tài)操作或同步控制。
// 錯(cuò)誤示例:線程不安全的累加
List<Integer> nums = Arrays.asList(1, 2, 3);
int[] sum = {0};
nums.parallelStream().forEach(n -> sum += n); // 結(jié)果可能錯(cuò)誤
// 正確做法:使用歸約
int safeSum = nums.parallelStream().reduce(0, Integer::sum);謹(jǐn)慎使用有狀態(tài)操作
如sorted()、distinct()在并行流中可能更耗時(shí),需合并線程結(jié)果。
// 并行排序(可能比順序流慢) List<Integer> sortedList = nums.parallelStream().sorted().toList();
數(shù)據(jù)源的可拆分性
- 高效結(jié)構(gòu):
ArrayList、數(shù)組(支持快速隨機(jī)訪問(wèn),易于分割)。 - 低效結(jié)構(gòu):
LinkedList、TreeSet(拆分成本高)。
順序敏感操作
使用forEachOrdered保證順序,但犧牲性能。
// 按順序輸出(性能低于無(wú)序操作) list.parallelStream().forEachOrdered(System.out::println);
配置線程池
默認(rèn)線程數(shù):
Runtime.getRuntime().availableProcessors()
修改全局線程數(shù):
# JVM啟動(dòng)參數(shù) -Djava.util.concurrent.ForkJoinPool.common.parallelism=8
5. 性能對(duì)比示例
// 順序流 vs 并行流(處理1000萬(wàn)數(shù)據(jù))
List<Long> numbers = LongStream.rangeClosed(1, 10_000_000)
.boxed().collect(Collectors.toList());
// 順序流耗時(shí)
long start = System.currentTimeMillis();
long seqSum = numbers.stream().mapToLong(n -> n * 2).sum();
System.out.println("順序流耗時(shí): " + (System.currentTimeMillis() - start) + "ms");
// 并行流耗時(shí)
start = System.currentTimeMillis();
long parSum = numbers.parallelStream().mapToLong(n -> n * 2).sum();
System.out.println("并行流耗時(shí): " + (System.currentTimeMillis() - start) + "ms");典型結(jié)果(8核CPU):
順序流耗時(shí): 120ms 并行流耗時(shí): 35ms
總結(jié)
優(yōu)勢(shì):簡(jiǎn)化多線程編程,提升大數(shù)據(jù)處理效率。
局限:不適合小數(shù)據(jù)量、順序敏感或低計(jì)算量任務(wù)。
最佳實(shí)踐:
- 優(yōu)先處理大規(guī)模數(shù)據(jù)。
- 避免操作共享變量。
- 測(cè)試驗(yàn)證性能提升。
- 使用
forEach替代forEachOrdered除非必須保證順序。
通過(guò)合理使用并行流,可在不增加復(fù)雜代碼的情況下顯著提升程序性能,但需結(jié)合場(chǎng)景權(quán)衡利弊。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Idea連接GitLab的過(guò)程以及創(chuàng)建在gitlab中創(chuàng)建用戶和群組方式
本文介紹了如何在IDEA中連接GitLab,首先需安裝GitLab插件并配置SSH免密登錄,接著,創(chuàng)建GitLab個(gè)人令牌并在Git中配置,文章還提到了如何在GitLab中創(chuàng)建用戶、群組及設(shè)置權(quán)限,如Owner、Maintainer、Developer等,并強(qiáng)調(diào)了群組名和人員名稱的命名規(guī)范2024-11-11
Java實(shí)現(xiàn)的兩種常見(jiàn)簡(jiǎn)單查找算法示例【快速查找與二分查找】
這篇文章主要介紹了Java實(shí)現(xiàn)的兩種常見(jiàn)簡(jiǎn)單查找算法,結(jié)合具體實(shí)例形式分析了java快速查找與二分查找的原理與簡(jiǎn)單實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-09-09
idea數(shù)據(jù)庫(kù)驅(qū)動(dòng)下載失敗的問(wèn)題及解決
這篇文章主要介紹了idea數(shù)據(jù)庫(kù)驅(qū)動(dòng)下載失敗的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
Java.toCharArray()和charAt()的效率對(duì)比分析
這篇文章主要介紹了Java.toCharArray()和charAt()的效率對(duì)比分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-10-10
mybatis 運(yùn)行時(shí)加載自定義mapper文件方式
這篇文章主要介紹了mybatis 運(yùn)行時(shí)加載自定義mapper文件方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07
java 讀取系統(tǒng)Properties代碼實(shí)例
這篇文章主要介紹了java 讀取系統(tǒng)Properties代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11
SpringBoot使用Kaptcha實(shí)現(xiàn)驗(yàn)證碼的生成與驗(yàn)證功能
這篇文章主要介紹了SpringBoot使用Kaptcha實(shí)現(xiàn)驗(yàn)證碼的生成與驗(yàn)證功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03
java算法題解LeetCode35復(fù)雜鏈表的復(fù)制實(shí)例
這篇文章主要為大家介紹了java算法題解LeetCode35復(fù)雜鏈表的復(fù)制實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01

