查詢電腦的邏輯核心數(shù),不同業(yè)務(wù)下如何配置線程池

邏輯核心數(shù)

一般百度如何獲取電腦的邏輯核心數(shù),都會(huì)出現(xiàn)這段代碼:

Runtime.getRuntime().availableProcessors()

然而,問(wèn)題在于Runtime.getRuntime().availableProcessors()也并非都能返回你所期望的數(shù)值。比如說(shuō),在我的雙核1-2-1機(jī)器上,它返回的是2,這是對(duì)的。不過(guò)在我的1-4-2(1個(gè)物理處理器-4個(gè)核-每個(gè)核2個(gè)超線程=也就是通常說(shuō)的4核8線程)機(jī)器 上,也就是一個(gè)CPU插槽,4核,每個(gè)核2個(gè)超線程,這樣的話會(huì)返回8。不過(guò)我其實(shí)只有4個(gè)核,如果代碼的瓶頸是在CPU這塊的話,我會(huì)有7個(gè)線程在同時(shí) 競(jìng)爭(zhēng)CPU周期,而不是更合理的4個(gè)線程。如果我的瓶頸是在內(nèi)存這的話,那這個(gè)測(cè)試我可以獲得7倍的性能提升。

不過(guò)這還沒(méi)完!Java Champions上的一個(gè)哥們發(fā)現(xiàn)了一種情況,他有一臺(tái)16-4-2的機(jī)器 (也就是16個(gè)CPU插槽,每個(gè)CPU4個(gè)核,每核兩個(gè)超線程,返回的值居然是16!從我的i7 Macbook pro上的結(jié)果來(lái)看,我覺(jué)得應(yīng)該返回的是1642=128。在這臺(tái)機(jī)器上運(yùn)行Java 8的話,它只會(huì)將通用的FJ池的并發(fā)數(shù)設(shè)置成15。正如 Brian Goetz所指出的,“虛擬機(jī)其實(shí)不清楚什么是處理器,它只是去請(qǐng)求操作系統(tǒng)返回一個(gè)值。同樣的,操作系統(tǒng)也不知道怎么回事,它是去問(wèn)的硬件設(shè)備。硬件會(huì)告訴它一個(gè)值,通常來(lái)說(shuō)是硬件線程數(shù)。操作系統(tǒng)相信硬件說(shuō)的,而虛擬機(jī)又相信操作系統(tǒng)說(shuō)的。”

所以不同業(yè)務(wù)下的情況不盡相同,不能一概而論都根據(jù)核心數(shù)量去統(tǒng)一配置線程池。

那么如果我們線程池主要用于處理 IO 密集型的任務(wù)時(shí),如讀取文件,數(shù)據(jù)庫(kù)連接,網(wǎng)絡(luò)通訊等,我們都知道 IO 讀寫的速度,與CPU相比的話,肯定是慢的多,所以一般建議去機(jī)器邏輯核心數(shù)的 2 倍。

多個(gè)線程池

一般項(xiàng)目可能會(huì)創(chuàng)建多個(gè)線程池,因?yàn)楸热?種業(yè)務(wù),一種要求不高,但是數(shù)量極多,可以重試,一種是數(shù)量小,要求及時(shí),如果放在一起,會(huì)因?yàn)槎嗟臄?shù)量可能影響你那筆少的,

線程池用來(lái)管理線程,一般需要一個(gè)定時(shí)線程池,一個(gè)業(yè)務(wù)線程池,一個(gè)io線程池,有的時(shí)候,定時(shí)線程池和業(yè)務(wù)線程池也可以共用,比如netty的線程池就可以共用。業(yè)務(wù)線程池用于處理核心業(yè)務(wù),一般要求速度快,延遲低,而io線程池一般用于網(wǎng)絡(luò)交互,比如數(shù)據(jù)庫(kù)操作,rpc請(qǐng)求,或者磁盤讀寫。

業(yè)務(wù)場(chǎng)景

主要要先看我們線程池用于執(zhí)行的任務(wù)性質(zhì)。如果該線程池主要用于處理計(jì)算密集型的任務(wù)時(shí),如加密、大數(shù)分解等主要利用CPU資源的任務(wù),一般建議將我們的線程數(shù)設(shè)置為機(jī)器的核心數(shù)(邏輯核心)+ 1

這里為什么要進(jìn)行加一呢?這是為了避免我們CPU會(huì)出現(xiàn)頁(yè)缺失的情況(頁(yè)缺失是指線程執(zhí)行所需的數(shù)據(jù)還未來(lái)來(lái)的及加載,部分還存在于磁盤之上,那么這個(gè)線程就會(huì)被掛起。)


那么如果我們線程池主要用于處理 IO 密集型的任務(wù)時(shí),如讀取文件,數(shù)據(jù)庫(kù)連接,網(wǎng)絡(luò)通訊等,我們都知道 IO 讀寫的速度,與CPU相比的話,肯定是慢的多,所以一般建議去機(jī)器邏輯核心數(shù)的 2 倍。

另外如果我們線程池既處理計(jì)算密集型任務(wù),也處理IO密集型任務(wù)時(shí)。那么我們應(yīng)該如何處理?

IO 密集型所花費(fèi)的時(shí)間遠(yuǎn)大于計(jì)算密集型花費(fèi)的時(shí)間,拆分意義不大,這時(shí)就沒(méi)有必要拆分;但是如果 IO 密集型花費(fèi)的時(shí)間約等于計(jì)算密集型的時(shí)間,則建議將其拆分開(kāi)來(lái)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容