轉 根據CPU核心數肯定線程池併發線程數

轉自: https://www.cnblogs.com/dennyzhangdd/p/6909771.html?utm_source=itdadao&utm_medium=referralhtml

 

 

正文算法

1、拋出問題

關於如何計算併發線程數,通常分兩派,來自兩本書,且都是好書,到底哪一個是對的?問題追蹤後,整理以下:數據庫

第一派:《Java Concurrency in Practice》即《java併發編程實踐》,以下圖:編程

 

如上圖,在《Java Concurrency in Practice》一書中,給出了估算線程池大小的公式:swift

Nthreads=Ncpu*Ucpu*(1+w/c),其中服務器

Ncpu=CPU核心數網絡

Ucpu=cpu使用率,0~1多線程

W/C=等待時間與計算時間的比率併發

 

第二派:《Programming Concurrency on the JVM Mastering》即《Java 虛擬機併發編程》

線程數=Ncpu/(1-阻塞係數)

2、分析

對於派系一,假設cpu100%運轉,即撇開CPU使用率這個因素,線程數=Ncpu*(1+w/c)。

如今假設將派系二的公式等於派系一公式,即Ncpu/(1-阻塞係數)=Ncpu*(1+w/c),===》阻塞係數=w/(w+c),即阻塞係數=阻塞時間/(阻塞時間+計算時間),這個結論在派系二後續中獲得應徵,以下圖:

因而可知,派系一和派系二實際上是一個公式......這樣我就放心了......

 

3、實際應用

那麼實際使用中併發線程數如何設置呢?分析以下(咱們以派系一公式爲例):

Nthreads=Ncpu*(1+w/c)

IO密集型:通常狀況下,若是存在IO,那麼確定w/c>1(阻塞耗時通常都是計算耗時的不少倍),可是須要考慮系統內存有限(每開啓一個線程都須要內存空間),這裏須要上服務器測試具體多少個線程數適合(CPU佔比、線程數、總耗時、內存消耗)。若是不想去測試,保守點取1即,Nthreads=Ncpu*(1+1)=2Ncpu。這樣設置通常都OK。

計算密集型:假設沒有等待w=0,則W/C=0. Nthreads=Ncpu。

至此結論就是:

IO密集型=2Ncpu(能夠測試後本身控制大小,2Ncpu通常沒問題)(常出現於線程中:數據庫數據交互、文件上傳下載、網絡數據傳輸等等)

計算密集型=Ncpu(常出現於線程中:複雜算法)

java中:Ncpu=Runtime.getRuntime().availableProcessors()

=========================此處可略過=============================================

固然派系一種《Java Concurrency in Practice》還有一種說法,

即對於計算密集型的任務,在擁有N個處理器的系統上,當線程池的大小爲N+1時,一般能實現最優的效率。(即便當計算密集型的線程偶爾因爲缺失故障或者其餘緣由而暫停時,這個額外的線程也能確保CPU的時鐘週期不會被浪費。)

即,計算密集型=Ncpu+1,可是這種作法致使的多一個cpu上下文切換是否值得,這裏不考慮。讀者可本身考量。

======================================================================

4、總結

選擇線程池併發線程數的因素不少:任務類型、內存等線程中使用到全部資源都須要考慮。本文通過對現有文獻的分析論證,得出結論,並給出了實際應用公式,實乃工程師之福利,技術之典範......

 

 

---

一針見血系列[2]: 線程池裏面到底該設置多少個線程呢?論Java多線程和CPU核數的關係

轉自: http://swiftlet.net/archives/3012

在Java中,經過下面的代碼,咱們能夠很容易地獲取到系統可用的處理器核心數目:

基本原則是:應用程序的最小線程數應該等於可用的處理器核數。具體場景又分爲如下兩種狀況:

(1)若是全部的任務都是計算密集型的,則建立處理器可用核心數那麼多個線程就能夠了。在這種狀況下,建立更多的線程對程序性能而言反而是不利的。由於當有多個任務處於就緒狀態時,處理器核心須要在線程間頻繁進行上下文切換,而這種切換對程序性能損耗較大。
(2)若是任務都是IO密集型的,那麼咱們就須要開更多的線程來提升性能。當一個任務執行IO操做時,其線程將被阻塞,因而處理器能夠當即進行上下文切換以便處理其餘就緒線程。若是咱們只有處理器可用核心數那麼多個線程的話,即便有待執行的任務也沒法處理,由於咱們已經拿不出更多的線程供處理器調度了。
總之,若是任務有50%的時間處於阻塞狀態,則程序所需線程數爲處理器可用核心數的兩倍。若是任務被阻塞的時間少於50%,即這些任務是計算密集型的,則程序所需線程數將隨之減小,但最少也不該低於處理器的核心數。若是任務被阻塞的時間大於執行時間,即該任務是IO密集型的,咱們就須要建立比處理器核心數大幾倍數量的線程。計算出程序所需線程的總數的公式以下:

線程數=CPU可用核心數/(1-阻塞係數),其中阻塞係數的取值在0和1之間。

計算密集型任務的阻塞係數爲0,而IO密集型任務的阻塞係數則接近1。一個徹底阻塞的任務是註定要掛掉的,因此咱們無須擔憂阻塞係數會達到1。

相關文章
相關標籤/搜索