每天淩晨00點00分, 第一時間與你相約
每日英文
No one can go to bear for you, no one can get to get you strong.
沒有人能夠去替你承受,也沒有人能夠拿得走你的堅強。
每日掏心話
有時候,雖然能想明白,但心裡就是接受不了。大道理人人都懂,小情緒卻難以自控。
來自:隻會一點java | 責編:樂樂
程式員小樂(ID:study_tech)第 951 次推文 圖源:百度
往日回顧:計算機網絡基礎知識總結
正文
關于如何計算并發線程數,一般分兩派,來自兩本書,且都是好書,到底哪個是對的?問題追蹤後,整理如下:
第一派:《Java Concurrency in Practice》即《java并發程式設計實踐》,如下圖:
如上圖,在《Java Concurrency in Practice》一書中,給出了估算線程池大小的公式:
Nthreads=NcpuUcpu(1+w/c),其中
Ncpu=CPU核心數
Ucpu=cpu使用率,0~1
W/C=等待時間與計算時間的比率
關注公衆号程式員小樂回複關鍵字“Java”擷取Java面試題和答案。
第二派:《Programming Concurrency on the JVM Mastering》即《Java 虛拟機并發程式設計》
線程數=Ncpu/(1-阻塞系數)
對于派系一,假設cpu100%運轉,即撇開CPU使用率這個因素,線程數=Ncpu*(1+w/c)。
現在假設将派系二的公式等于派系一公式,即Ncpu/(1-阻塞系數)=Ncpu*(1+w/c),===》阻塞系數=w/(w+c),即阻塞系數=阻塞時間/(阻塞時間+計算時間),這個結論在派系二後續中得到應征,如下圖:
由此可見,派系一和派系二其實是一個公式……這樣我就放心了……
那麼實際使用中并發線程數如何設定呢?分析如下(我們以派系一公式為例):
<code>Nthreads=Ncpu*(1+w/c)</code>
IO密集型:一般情況下,如果存在IO,那麼肯定w/c>1(阻塞耗時一般都是計算耗時的很多倍),但是需要考慮系統記憶體有限(每開啟一個線程都需要記憶體空間),這裡需要上伺服器測試具體多少個線程數适合(CPU占比、線程數、總耗時、記憶體消耗)。如果不想去測試,保守點取1即,Nthreads=Ncpu*(1+1)=2Ncpu。這樣設定一般都OK。擴充一下:JAVA多線程和并發基礎面試問答
計算密集型:假設沒有等待w=0,則W/C=0. Nthreads=Ncpu。
至此結論就是:
IO密集型=2Ncpu(可以測試後自己控制大小,2Ncpu一般沒問題)(常出現于線程中:資料庫資料互動、檔案上傳下載下傳、網絡資料傳輸等等)
<code>計算密集型=Ncpu(常出現于線程中:複雜算法)</code>
java中:<code>Ncpu=Runtime.getRuntime().availableProcessors()</code>
關注公衆号程式員小樂回複關鍵字“offer”擷取算法面試題和答案。
當然派系一種《Java Concurrency in Practice》還有一種說法,
即對于計算密集型的任務,在擁有N個處理器的系統上,當線程池的大小為N+1時,通常能實作最優的效率。(即使當計算密集型的線程偶爾由于缺失故障或者其他原因而暫停時,這個額外的線程也能確定CPU的時鐘周期不會被浪費。)
即,計算密集型=Ncpu+1,但是這種做法導緻的多一個cpu上下文切換是否值得,這裡不考慮。讀者可自己考量。
選擇線程池并發線程數的因素很多:任務類型、記憶體等線程中使用到所有資源都需要考慮。
歡迎在留言區留下你的觀點,一起讨論提高。如果今天的文章讓你有新的啟發,歡迎轉發分享給更多人。歡迎加入程式員小樂技術交流群。
猜你還想看
阿裡、騰訊、百度、華為、京東最新面試題彙集
教你設計一個超牛逼的本地緩存!
Netty是個啥?簡單來說就這!
面試官:為什麼 wait() 方法需要寫在while裡、而不是if? 我回答不上來