邏輯核心數(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 讀寫(xiě)的速度,與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)求,或者磁盤(pán)讀寫(xiě)嫌变。
業(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)的及加載倘待,部分還存在于磁盤(pán)之上软啼,那么這個(gè)線程就會(huì)被掛起。)
那么如果我們線程池主要用于處理 IO 密集型的任務(wù)時(shí)延柠,如讀取文件,數(shù)據(jù)庫(kù)連接锣披,網(wǎng)絡(luò)通訊等贞间,我們都知道 IO 讀寫(xiě)的速度,與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)吭从。