線程數,射多少更舒適?

来源:https://www.cnblogs.com/wupeixuan/archive/2020/03/25/12563640.html
-Advertisement-
Play Games

我相信大家都用過線程池,但是線程池數量設置為多少比較合理呢? 線程數的設置的最主要的目的是為了充分併合理地使用 CPU 和記憶體等資源,從而最大限度地提高程式的性能,因此讓我們一起去探索吧! 首先要考慮到 CPU 核心數,那麼在 Java 中如何獲取核心線程數? 可以使用 方法來獲取(可能不准確,作為 ...


我相信大家都用過線程池,但是線程池數量設置為多少比較合理呢?

線程數的設置的最主要的目的是為了充分併合理地使用 CPU 和記憶體等資源,從而最大限度地提高程式的性能,因此讓我們一起去探索吧!

首先要考慮到 CPU 核心數,那麼在 Java 中如何獲取核心線程數?

可以使用 Runtime.getRuntime().availableProcessor() 方法來獲取(可能不准確,作為參考)

在確認了核心數後,再去判斷是 CPU 密集型任務還是 IO 密集型任務:

  • CPU 密集型任務:比如像加解密,壓縮、計算等一系列需要大量耗費 CPU 資源的任務,大部分場景下都是純 CPU 計算
  • IO 密集型任務:比如像 MySQL 資料庫、文件的讀寫、網路通信等任務,這類任務不會特別消耗 CPU 資源,但是 IO 操作比較耗時,會占用比較多時間

在知道如何判斷任務的類別後,讓我們分兩個場景進行討論:

CPU 密集型任務

對於 CPU 密集型計算,多線程本質上是提升多核 CPU 的利用率,所以對於一個 8 核的 CPU,每個核一個線程,理論上創建 8 個線程就可以了。

如果設置過多的線程數,實際上並不會起到很好的效果。此時假設我們設置的線程數量是 CPU 核心數的 2 倍,因為計算任務非常重,會占用大量的 CPU 資源,所以這時 CPU 的每個核心工作基本都是滿負荷的,而我們又設置了過多的線程,每個線程都想去利用 CPU 資源來執行自己的任務,這就會造成不必要的上下文切換,此時線程數的增多並沒有讓性能提升,反而由於線程數量過多會導致性能下降。

因此,對於 CPU 密集型的計算場景,理論上線程的數量 = CPU 核數就是最合適的,不過通常把線程的數量設置為CPU 核數 +1,會實現最優的利用率。即使當密集型的線程由於偶爾的記憶體頁失效或其他原因導致阻塞時,這個額外的線程也能確保 CPU 的時鐘周期不會被浪費,從而保證 CPU 的利用率。

如下圖就是在一個 8 核 CPU 的電腦上,通過修改線程數來測試對 CPU 密集型任務(素數計算)的性能影響。

可以看到線程數小於 8 時,性能是很差的,線上程數多於處理器核心數對性能的提升也很小,因此可以驗證公式還是具有一定適用性的。

除此之外,我們最好還要同時考慮在同一臺機器上還有哪些其他會占用過多 CPU 資源的程式在運行,然後對資源使用做整體的平衡。

IO 密集型任務

對於 IO 密集型任務最大線程數一般會大於 CPU 核心數很多倍,因為 IO 讀寫速度相比於 CPU 的速度而言是比較慢的,如果我們設置過少的線程數,就可能導致 CPU 資源的浪費。而如果我們設置更多的線程數,那麼當一部分線程正在等待 IO 的時候,它們此時並不需要 CPU 來計算,那麼另外的線程便可以利用 CPU 去執行其他的任務,互不影響,這樣的話在任務隊列中等待的任務就會減少,可以更好地利用資源。

對於 IO 密集型計算場景,最佳的線程數是與程式中 CPU 計算和 IO 操作的耗時比相關的,《Java併發編程實戰》的作者 Brain Goetz 推薦的計算方法如下:

線程數 = CPU 核心數 * (1 + IO 耗時/ CPU 耗時)

通過這個公式,我們可以計算出一個合理的線程數量,如果任務的平均等待時間長,線程數就隨之增加,而如果平均工作時間長,也就是對於我們上面的 CPU 密集型任務,線程數就隨之減少。可以採用 APM 工具統計到每個方法的耗時,便於計算 IO 耗時和 CPU 耗時。

在這裡引用Java併發編程實戰中的圖,方便大家更容易理解:

三線程執行示意圖

還有一派的計算方式是《Java虛擬機併發編程》中提出的:

線程數 = CPU 核心數 / (1 - 阻塞繫數)

其中計算密集型阻塞繫數為 0,IO 密集型阻塞繫數接近 1,一般認為在 0.8 ~ 0.9 之間。比如 8 核 CPU,按照公式就是 2 / ( 1 - 0.9 ) = 20 個線程數

上圖是 IO 密集型任務的一個測試,是在雙核處理器上開不同的線程數(從 1 到 40)來測試對程式性能的影響,可以看到線程池數量達到 20 之後,曲線逐漸水平,說明開再多的線程對程式的性能提升也毫無幫助。

太少的線程數會使得程式整體性能降低,而過多的線程也會消耗記憶體等其他資源,所以如果想要更準確的話,可以進行壓測,監控 JVM 的線程情況以及 CPU 的負載情況,根據實際情況衡量應該創建的線程數,合理並充分利用資源。

同時,有很多線程池的應用,比如 Tomcat、Redis、Jdbc 等,每個應用設置的線程數也是不同的,比如 Tomcat 為流量入口,那麼線程數的設置可能就要比其他應用要大。

總結

通過對線程數設置的探究,我們可以得知線程數的設置首先和 CPU 核心數有莫大關聯,除此之外,我們需要根據任務類型的不同選擇對應的策略,線程的平均工作時間所占比例越高,就需要越少的線程;線程的平均等待時間所占比例越高,就需要越多的線程;針對不同的程式,進行對應的實際測試就可以得到最合適的選擇。

參考

《Java併發編程實戰》

《Java虛擬機併發編程》

Java併發編程實戰

Java併發編程核心


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

-Advertisement-
Play Games
更多相關文章
  • 因為IT互聯網發展的非常迅速,而web前端這塊很火,目前工資水平給的很高,在市場上也是非常的稀缺人才,現在各個行業轉行做web前端的很多,今天給大家一些建議,希望新手少走點彎路吧! 建議一:有一個比較適合自己系統的學習方案,系統的學習教程,很多人在開始學習web前端的時候都不知道如何規劃,也不知道w ...
  • 事件冒泡通俗講以整個文檔體doucment參照就是從裡到外(可以自行腦補一下水裡冒泡現象) 說到事件冒泡就不得不提一下dom0級事件與dom2及事件 dom0級事件會覆蓋,如下控制台只會輸出結果 2: var oDiv=document.getElementById('div'); oDiv.onc ...
  • 如何實現一個parseInt 如果string不為字元串類型, 則先將string轉化為字元串類型 string會忽略前後的空白 依次解析字元, 如果字元不是指定基數中的字元( 例如:2進位中的3、 10進位中的'f' )則停止解析( 首字元為'+'或' '時除外 ), 返回已經解析好的整數 如果無 ...
  • HTML5 Geolocation 定位用戶的位置 HTML5 Geolocation API 用於獲得用戶的地理位置。 鑒於該特性可能侵犯用戶的隱私,除非用戶同意,否則用戶位置信息是不可用的。 註意: Geolocation(地理定位)對於擁有 GPS 的設備,比如 iPhone,地理定位更加精確 ...
  • 用Javascript的while迴圈,列印九九乘法表 用Javascript的while迴圈: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>列印九九乘法表</title> <script type="text/javasc ...
  • css3系列 2.css中常見的樣式屬性和值 繼續上一篇文章的繼續瞭解css的基礎知識,關註我微信公眾號:全棧學習筆記 css中常見的樣式屬性和值 1. 字體與顏色 1. 背景屬性 2. 文本屬性 1. 邊框屬性 1. 內外邊距 1. 滑鼠游標屬性 1. 列表樣式 1. 定位屬性 1. 浮動和清除浮 ...
  • 一、委派模式 委派模式(Delegate Pattern):指負責任務的調度和分配任務,跟代理模式很像,可以看做是一種特殊情況下的靜態代理的全權代理,但是代理模式註重過程,而委派模式註重結果。(屬於行為型模式,但它不屬於GOF的23種設計模式之一。類名以Delegate和Dispatcher結尾的一 ...
  • 圖解Java設計模式之組合模式 看一個學校院系展示需求 傳統方案解決學院院系展示(類圖) 傳統方案解決學校院系展示存在的問題分析 組合模式基本介紹 組合模式的原理類圖 組合模式解決學校院系展示的應用實例 組合模式在JDK集合的源碼分析 組合模式的註意事項和細節 看一個學校院系展示需求 編寫程式展示一 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...