java8中parallelStream提升數倍查詢效率是怎樣實現的,來看看這篇文章

来源:https://www.cnblogs.com/MonsterJ/archive/2020/07/20/13347722.html
-Advertisement-
Play Games

作者:我恰芙蓉王 原文:https://www.cnblogs.com/-tang/p/13283216.html 業務場景 在很多項目中,都有類似數據彙總的業務場景,查詢今日註冊會員數,線上會員數,訂單總金額,支出總金額等。。。這些業務通常都不是存在同一張表中,我們需要依次查詢出來然後封裝成所需要 ...


在這裡插入圖片描述

作者:我恰芙蓉王

原文:https://www.cnblogs.com/-tang/p/13283216.html

業務場景

在很多項目中,都有類似數據彙總的業務場景,查詢今日註冊會員數,線上會員數,訂單總金額,支出總金額等。。。這些業務通常都不是存在同一張表中,我們需要依次查詢出來然後封裝成所需要的對象返回給前端。那麼在此過程中,就可以把這個介面中“大任務”拆分成N個小任務,非同步執行這些小任務,等到最後一個小任務執行完,把所有任務的執行結果封裝到返回結果中,統一返回到前端展示。

同步執行

首先看看同步執行的代碼

public class Test {


    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @ToString
    class Result {
        /**
         * 線上人數
         */
        Integer onlineUser;

        /**
         * 註冊人數
         */
        Integer registered;

        /**
         * 訂單總額
         */
        BigDecimal orderAmount;

        /**
         * 支出總額
         */
        BigDecimal outlayAmount;
    }

    @org.junit.Test
    public void collect() {
        System.out.println("數據彙總開始");
        long startTime = System.currentTimeMillis();
        Integer onlineUser = queryOnlineUser();
        Integer registered = queryRegistered();
        BigDecimal orderAmount = queryOrderAmount();
        BigDecimal outlayAmount = queryOutlayAmount();
        Result result = new Result(onlineUser, registered, orderAmount, outlayAmount);
        long endTime = System.currentTimeMillis();
        System.out.println("獲取彙總數據結束,result = " + result);
        System.out.println("總耗時 = " + (endTime - startTime) + "毫秒");
    }

    public Integer queryOnlineUser() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("查詢線上人數 耗時2秒");
        return 10;
    }

    public Integer queryRegistered() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("查詢註冊人數 耗時2秒");
        return 10086;
    }

    public BigDecimal queryOrderAmount() {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("查詢訂單總額 耗時3秒");
        return BigDecimal.valueOf(2000);
    }

    public BigDecimal queryOutlayAmount() {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("查詢支出總額 耗時3秒");
        return BigDecimal.valueOf(1000);
    }

}
 

 

執行時長想必大家都能夠想得到,理所應當是10秒以上

數據彙總開始
查詢線上人數 耗時2秒
查詢註冊人數 耗時2秒
查詢訂單總額 耗時3秒
查詢支出總額 耗時3秒
獲取彙總數據結束,result = Test.Result(onlineUser=10, registered=10086, orderAmount=2000, outlayAmount=1000)
總耗時 = 10008毫秒

非同步執行

下麵換成非同步執行,用java8的parallelStream(並行流),這裡為什麼不用Thread呢,這裡有一個註意點,我們需要獲取所有所有子任務執行完的時間點,在這個時間點之後才能將結果封裝返回,Thread沒有辦法滿足,這裡parallelStream和函數式介面就登場了。

java8的特性之一 —— lambda表達式,就是配合函數式介面使用的。

java8內置了四大核心函數式介面:

1、Consumer : 消費型介面 void accept(T t);

2、Supplier : 供給型介面 T get();

3、Function<T,R> : 函數型介面 R apply(T t);

4、Predicate : 斷言型介面 boolean test(T t);

這四大核心函數式介面其下還有很多子介面,基本上能滿足日常項目所用,這裡扯遠了。。 直接上代碼。

這裡我們需要使用的是Runable介面,是無參無返回值的一個介面。在實際場景中,可能有時間範圍之類的查詢參數的,則可以根據不同業務使用不同的介面。這種方式也可以用Future介面去實現,有興趣的可以試一試,這裡就不多做敘述了。

@org.junit.Test
public void collect() {
    System.out.println("數據彙總開始");
    long startTime = System.currentTimeMillis();
    Result result = new Result();
    List<Runnable> taskList = new ArrayList<Runnable>() {
        {
            add(() -> result.setOnlineUser(queryOnlineUser()));
            add(() -> result.setRegistered(queryRegistered()));
            add(() -> result.setOrderAmount(queryOrderAmount()));
            add(() -> result.setOutlayAmount(queryOutlayAmount()));
        }
    };
    taskList.parallelStream().forEach(v -> v.run());
    long endTime = System.currentTimeMillis();
    System.out.println("獲取彙總數據結束,result = " + result);
    System.out.println("總耗時 = " + (endTime - startTime) + "毫秒");
}

執行結果,由於四個子任務都是並行的,效率直接提升了三倍,如果子任務越多的話提升效果越明顯。

數據彙總開始
查詢線上人數 耗時2秒
查詢註冊人數 耗時2秒
查詢訂單總額 耗時3秒
查詢支出總額 耗時3秒
獲取彙總數據結束,result = Test.Result(onlineUser=10, registered=10086, orderAmount=2000, outlayAmount=1000)
總耗時 = 3079毫秒

總結

1.parallelStream是非同步編程的好幫手,在使用過程中一定要註意線程安全的問題。

2.以上這種方式只能用在沒有事務的業務中,因為在多線程中,事務是不共用的。

最後

私信回覆 資料 領取一線大廠Java面試題總結+阿裡巴巴泰山手冊+各知識點學習思維導+一份300頁pdf文檔的Java核心知識點總結!

這些資料的內容都是面試時面試官必問的知識點,篇章包括了很多知識點,其中包括了有基礎知識、Java集合、JVM、多線程併發、spring原理、微服務、Netty 與RPC 、Kafka、日記、設計模式、Java演算法、資料庫、Zookeeper、分散式緩存、數據結構等等。
file


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

-Advertisement-
Play Games
更多相關文章
  • class ListNode: def __init__(self, x): self.val = x self.next = Noneclass Solution: def swapPairs(self, head: ListNode) -> ListNode: # 定義一個節點,並將它指向頭結點 ...
  • class ListNode: def __init__(self, x): self.val = x self.next = None# 快慢指針的做法,定義兩個指針,一個走一步,一個走兩步# 如果他們不相遇的話,那就是沒有環,如果在某一時刻相遇,# 就說明是有環的。class Solution: ...
  • 隨著人工智慧以及腳本開發火熱,Python已經被推上一個非常火熱的巔峰! 那麼,想要學習Python卻又不知道從哪裡開始的朋友,看這裡呀~ Python在整個編程語言來說,是比較容易上手,而且“見效”特別快的! 下麵我就來推薦一些比較好上手,而且會讓整個學習過程變得更加輕鬆而快速! 基礎學習 進階技 ...
  • # Definition for singly-linked list.class ListNode: def __init__(self, x): self.val = x self.next = Nonea = ListNode(1)b = ListNode(2)a.next = b# 有關鏈表 ...
  • 如果不是領導強制要求,可能根本不會留意到這款號稱世界上功能最強大的開源資料庫——PostgreSQL。如果你不讀這篇文章,或許也會錯過一個躍躍欲試想擠進前三的優秀資料庫。 為了能夠熟練運用,特意買書研究,發現這款資料庫還真有點意思。彙總一篇文章與大家分享,目的只有一個:讓大家多少瞭解一下這款資料庫。 ...
  • 函數的本質就是**一段有特定功能、可以重覆使用的代碼**,這段代碼已經被提前編寫好了,並且為其起一個好聽的名字。在後續編寫程式過程中,如果需要同樣的功能,直接通過起好的名字就可以調用這段代碼。 ...
  • JDBC 獲取自增長id以及表的元數據 步驟 1 : 獲取自增長id 在Statement通過execute或者executeUpdate執行完插入語句後,MySQL會為新插入的數據分配一個自增長id,(前提是這個表的id設置為了自增長,在Mysql創建表的時候,AUTO_INCREMENT就表示自 ...
  • from typing import List# 這道題很容易能夠想到,只需要遍歷兩邊列表就可以了# 兩層迴圈class Solution: def twoSum(self, numbers: List[int], target: int) -> List[int]: # 第一次遍歷列表 for i ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...