求求你們了,別再亂用 parallelStream 了,速度竟然比 Stream 還要慢!!

来源:https://www.cnblogs.com/javastack/archive/2022/09/02/16650116.html
-Advertisement-
Play Games

parallelStream 一定更快嗎? 大家都知道 Stream 分為順序流和並行流: stream(順序流) parallelStream(並行流) 它們最大的區別就是 parallelStream 支持並行化處理,所以效率較 stream(順序流)肯定是要更快的。這篇不會介紹 Stream ...


parallelStream 一定更快嗎?

大家都知道 Stream 分為順序流和並行流:

  • stream(順序流)
  • parallelStream(並行流)

它們最大的區別就是 parallelStream 支持並行化處理,所以效率較 stream(順序流)肯定是要更快的。這篇不會介紹 Stream 基礎,Stream 系列我之前寫過一個專題了,不懂的關註公眾號Java技術棧,然後在公眾號 Java 教程菜單中閱讀。

然而你確定 parallelStream 一定要更快嗎?

棧長寫了一段排序的示例,分別用 stream 和 parallelStream,對 100 ~ 10000000 條數據的集合進行排序,來看下執行效率究竟如何!

順序流排序:

/**
 * 順序流排序
 * @author: 棧長
 * @from: 公眾號Java技術棧
 */
private static void streamSort() {
    long start = System.currentTimeMillis();
    List<SortTest.User> list = new ArrayList<>(LIST);

    list.stream().sorted(SortTest.User::compareAge).collect(Collectors.toList());

    System.out.println("\nList size: " + list.size() + " Stream.sorted: " + (System.currentTimeMillis() - start));
}

並行流排序:

/**
 * 並行流排序
 * @author: 棧長
 * @from: 公眾號Java技術棧
 */
private static void parallelStreamSort() {
    long start = System.currentTimeMillis();
    List<SortTest.User> list = new ArrayList<>(LIST);

    list.parallelStream().sorted(SortTest.User::compareAge).collect(Collectors.toList());

    System.out.println("List size: " + list.size() + " ParallelStream.sorted: " + (System.currentTimeMillis() - start));
}

本文所有完整示例源代碼已經上傳:

https://github.com/javastacks/javastack

執行結果如下:

List size: 10000000 Stream.sorted: 202
List size: 10000000 ParallelStream.sorted: 402

List size: 1000000 Stream.sorted: 53
List size: 1000000 ParallelStream.sorted: 15

List size: 100000 Stream.sorted: 1
List size: 100000 ParallelStream.sorted: 2

List size: 10000 Stream.sorted: 0
List size: 10000 ParallelStream.sorted: 1

List size: 1000 Stream.sorted: 0
List size: 1000 ParallelStream.sorted: 1

List size: 100 Stream.sorted: 0
List size: 100 ParallelStream.sorted: 0

在 100000 以下是沒什麼區別的;

在 1000000 左右 ParallelStream 雖然領先 Stream,但也不是絕對每次都領先,經過不斷測試,這個數據量區間的測試兩者會互相領先;

在 10000000 左右就很穩定了,ParallelStream 幾乎比 Stream 慢了 2 倍!

現在你可能會有疑問了,為什麼會這樣?

棧長起初也有疑問,並行流(ParallelStream)怎麼會比順序流(Stream)還要慢。。

其實我後面想想也就明白了,並行流(ParallelStream)的背後其實是 Java7 開始支持的 Fork/Join,即把一個大任務拆分成 N 個小任務,然後最終合併各個子任務的結果,所以對於子任務線程的拆分、創建、結果合併等操作都需要不少的開銷,特別是線程的創建。

所以這種不耗時的簡單排序操作事實上是不適用於並行流(ParallelStream)的,它所帶來的線程創建的損耗可能還會比順序流(Stream)還要更慢。

最新 Java 8+ 面試題也都整理好了,點擊Java面試庫小程式線上刷題。

什麼時候用 ParallelStream?

既然使用 Fork/Join 是會有損耗的,那對於單條數據的處理的時間最好是理論上要超過用並行流(ParallelStream)本身的損耗,這種情況下就比較合適。

也就是說,如果對於流中的每條數據的處理比較費時間,並且沒有順序要求,這種場景下用並行流(ParallelStream)會更快,更合適。

來看下麵這個示例:

順序流數據處理:

/**
 * 順序流數據處理
 * @author: 棧長
 * @from: 公眾號Java技術棧
 */
private static void streamProcess() {
    long start = System.currentTimeMillis();
    List<SortTest.User> list = new ArrayList<>(LIST);

    list.stream().map(StreamSpeedTest::process).collect(Collectors.toList());

    System.out.println("\nList size: " + list.size() + " Stream process: " + (System.currentTimeMillis() - start));
}

並行流數據處理:

/**
 * 並行流數據處理
 * @author: 棧長
 * @from: 公眾號Java技術棧
 */
private static void parallelStreamProcess() {
    long start = System.currentTimeMillis();
    List<SortTest.User> list = new ArrayList<>(LIST);

    list.parallelStream().map(StreamSpeedTest::process).collect(Collectors.toList());

    System.out.println("List size: " + list.size() + " ParallelStream process: " + (System.currentTimeMillis() - start));
}

數據處理:

/**
 * 數據處理
 * @author: 棧長
 * @from: 公眾號Java技術棧
 */
private static SortTest.User process(SortTest.User user) {
    try {
        user.setName(user.getName() + ": process");
        Thread.sleep(5);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return user;
}

註意: 這裡加了個休眠 5 毫秒,為了體現真實的處理數據耗時。

本文所有完整示例源代碼已經上傳:

https://github.com/javastacks/javastack

並行流排序:

List size: 1000 Stream process: 5750
List size: 1000 ParallelStream process: 745

List size: 100 Stream process: 566
List size: 100 ParallelStream process: 77

結果很明顯了,不管測試多少次,並行流(ParallelStream)的處理速度都要比順序流(Stream)要快幾倍!!我這裡只測試了 100 和 1000 條數據,因為 10000 條以上的數據用順序流(Stream)可能要等非常久。

而且我程式中的處理邏輯只休眠了 5 毫秒,如果實際處理單條數據的耗時要比這個更長,那並行流(ParallelStream)的處理效率還會更明顯。

總結

稍微總結下:

  • stream: 適用於避免線程安全問題、要求順序執行、數據處理簡單不耗時的任務;
  • parallelStream: 適用於不存線上程安全問題、不需要順序性執行、數據處理比較耗時的任務;

所以,你學廢了嗎?趕緊發給身邊的同事看看吧,別再亂用 parallelStream 了!用的不好,存線上程安全問題不說,效率上可能還會適得其反。

大家如果對 Java 8 新增的知識點(Lambda、Stream、函數式介面等)還不會用的可以關註公眾號:Java技術棧,在 Java 教程菜單中閱讀,Java 8+ 系列教程我都寫了一堆了。

本文所有完整示例源代碼已經上傳:

https://github.com/javastacks/javastack

歡迎 Star 學習,後面 Java 示例都會在這上面提供!

好了,今天的分享就到這裡了,後面棧長會分享更多好玩的 Java 技術和最新的技術資訊,關註公眾號Java技術棧第一時間推送,我也將主流 Java 面試題和參考答案都整理好了,在公眾號後臺回覆關鍵字 "面試" 進行刷題。

最後,覺得我的文章對你用收穫的話,動動小手,給個在看、轉發,原創不易,棧長需要你的鼓勵。

版權聲明: 本文系公眾號 "Java技術棧" 原創,轉載、引用本文內容請註明出處,抄襲、洗稿一律投訴侵權,後果自負,並保留追究其法律責任的權利。

近期熱文推薦:

1.1,000+ 道 Java面試題及答案整理(2022最新版)

2.勁爆!Java 協程要來了。。。

3.Spring Boot 2.x 教程,太全了!

4.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這才是優雅的方式!!

5.《Java開發手冊(嵩山版)》最新發佈,速速下載!

覺得不錯,別忘了隨手點贊+轉發哦!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前文再續,之前一篇我們已經配置好了資料庫以及模板引擎,現在可以在邏輯層編寫具體業務代碼了,博客平臺和大多數線上平臺一樣,都是基於用戶賬號體系來進行操作,所以我們需要針對用戶表完成用戶賬號的CURD操作。 用戶後臺模板 首先用戶操作邏輯主要在後臺展現,所以模板應該單獨生成admin文件夾,和前臺模板進 ...
  • 資料庫說明文檔,在我們開發項目時是非常必要的,有時項目交付時,客戶也是需要讓我們提供的,而如果人工編寫,比如耗時,通過screw組件來生成文檔,非常方便。 源代碼和使用:https://github.com/pig-mesh/screw 添加依賴 <dependency> <groupId>cn.s ...
  • 《Python灰帽子》PDF高清版免費下載地址(點擊即可) 內容簡介 · · · · · · 《Python灰帽子》是由知名安全機構Immunity Inc的資深黑帽Justin Seitz主筆撰寫的一本關於編程語言Python如何被廣泛應用於黑客與逆向工程領域的書籍。老牌黑客,同時也是Immuni ...
  • 前言 😋 大家早好、午好、晚好吖~ 開發環境: 解釋器版本: python 3.8 代碼編輯器: pycharm 2021.2 requests: pip install requests pandas: pip install pandas pyecharts: pip install pyec ...
  • 摘要:本文主要講解灰度線性變換,基礎性知識希望對您有所幫助。 本文分享自華為雲社區《[Python圖像處理] 十六.圖像的灰度非線性變換之對數變換、伽馬變換》,作者:eastmount 。 本篇文章主要講解非線性變換,使用自定義方法對圖像進行灰度化處理,包括對數變換和伽馬變換。 一.圖像灰度非線性變 ...
  • 大家好,我是不才陳某~ RPC、gRPC、Thrift、HTTP,大家知道它們之間的聯繫和區別麽?這些都是面試常考的問題,今天帶大家先搞懂 RPC 和 gRPC。 在講述 gRPC 之前,我們需要先搞懂什麼是 RPC。 不 BB,直接上文章目錄: 什麼是 RPC ? RPC(Remote Proce ...
  • 一、如果是使用 Qt Designer設計界面的話,那麼如何將Qt Designer設計出來的界面(.ui 文件)與業務邏輯程式接合起來,如下兩個方法:方法一:將.ui 文件通過命令轉換成 .py文件,然後在業務邏輯代碼中進行import xxxx導入即可 1、進入 .ui文件所在目錄,然後用命令: ...
  • 蘋果發佈Xcode 7之後,可以打開正常的AppleID或實機上傳,而不是$ 99或$ 299,只要你可以在AppStore下載應用程式的AppleID。關於Mac系統和Xcode的安裝,如果不請參見原文描述,這裡只介紹使用Xcode7和普通AppID創建免費證書、個人資料。 文中測試環境是OSX ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...