面試官:線程池裏面到底該設置多少個線程?

1、拋出問題

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

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

面試官:線程池裏面到底該設置多少個線程?


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

Nthreads=Ncpu*Ucpu*(1+w/c),其中數據庫

Ncpu=CPU核心數編程

Ucpu=cpu使用率,0~1服務器

W/C=等待時間與計算時間的比率網絡

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

面試官:線程池裏面到底該設置多少個線程?


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

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、總結

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

相關文章
相關標籤/搜索