目錄
一箱靴、拋出問題
二、分析
三荷愕、實際應用
===========正文分割線=================
一衡怀、拋出問題
關于如何計算并發(fā)線程數,一般分兩派安疗,來自兩本書抛杨,且都是好書,到底哪個是對的荐类?問題追蹤后怖现,整理如下:
第一派:《Java Concurrency in Practice》即《java并發(fā)編程實踐》,如下圖:
如上圖玉罐,在《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 虛擬機并發(fā)編程》
線程數=Ncpu/(1-阻塞系數)
二.分析
對于派系一饶号,假設cpu100%運轉,即撇開CPU使用率這個因素璧亚,線程數=Ncpu*(1+w/c)讨韭。
現在假設將派系二的公式等于派系一公式脂信,即Ncpu/(1-阻塞系數)=Ncpu*(1+w/c),===》阻塞系數=w/(w+c)癣蟋,即阻塞系數=阻塞時間/(阻塞時間+計算時間),這個結論在派系二后續(xù)中得到應征狰闪,如下圖:
由此可見疯搅,派系一和派系二其實是一個公式......這樣我就放心了......
三、實際應用
那么實際使用中并發(fā)線程數如何設置呢埋泵?分析如下(我們以派系一公式為例):
Nthreads=Ncpu*(1+w/c)
IO密集型:一般情況下幔欧,如果存在IO罪治,那么肯定w/c>1(阻塞耗時一般都是計算耗時的很多倍),但是需要考慮系統(tǒng)內存有限(每開啟一個線程都需要內存空間),這里需要上服務器測試具體多少個線程數適合(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個處理器的系統(tǒng)上奄喂,當線程池的大小為N+1時铐殃,通常能實現最優(yōu)的效率。(即使當計算密集型的線程偶爾由于缺失故障或者其他原因而暫停時跨新,這個額外的線程也能確保CPU的時鐘周期不會被浪費富腊。)
即,計算密集型=Ncpu+1域帐,但是這種做法導致的多一個cpu上下文切換是否值得赘被,這里不考慮。讀者可自己考量肖揣。
======================================================================
四民假、總結:
選擇線程池并發(fā)線程數的因素很多:任務類型、內存等線程中使用到所有資源都需要考慮龙优。本文經過對現有文獻的分析論證羊异,得出結論,并給出了實際應用公式彤断,實乃工程師之福利野舶,技術之典范......