原文:http://tutorials.jenkov.com/java-concurrency/benefits.html
作者:Jakob Jenkov ? ? ? ?翻譯:古圣昌 ? ? ? ? ? ?校對(duì):歐振聰
盡管面臨很多挑戰(zhàn)昵观,多線程有一些優(yōu)點(diǎn)使得它一直被使用匆帚。這些優(yōu)點(diǎn)是:
1悼凑、資源利用率更好
2、程序設(shè)計(jì)在某些情況下更簡(jiǎn)單
3蒋得、程序響應(yīng)更快
資源利用率更好
想象一下,一個(gè)應(yīng)用程序需要從本地文件系統(tǒng)中讀取和處理文件的情景。比方說(shuō)鸵膏,從磁盤(pán)讀取一個(gè)文件需要5秒,處理一個(gè)文件需要2秒法焰。處理兩個(gè)文件則需要:
1 ? ? ?5秒讀取文件A
2 ? ? ?2秒處理文件A
3 ? ? ?5秒讀取文件B
4 ? ? ?2秒處理文件B
5 ? ? ?---------------------
6 ? ? 總共需要14秒
從磁盤(pán)中讀取文件的時(shí)候秧荆,大部分的CPU時(shí)間用于等待磁盤(pán)去讀取數(shù)據(jù)。在這段時(shí)間里埃仪,CPU非常的空閑乙濒。它可以做一些別的事情。通過(guò)改變操作的順序卵蛉,就能夠更好的使用CPU資源颁股。看下面的順序:
1 ? ? ? 5秒讀取文件A
2 ? ? ? 5秒讀取文件B +2秒處理文件A
3 ? ? ? 2秒處理文件B
4 ? ? ? ---------------------
5 ? ? ?總共需要12秒
CPU等待第一個(gè)文件被讀取完傻丝。然后開(kāi)始讀取第二個(gè)文件甘有。當(dāng)?shù)诙募诒蛔x取的時(shí)候,CPU會(huì)去處理第一個(gè)文件葡缰。記住亏掀,在等待磁盤(pán)讀取文件的時(shí)候,CPU大部分時(shí)間是空閑的泛释。
總的說(shuō)來(lái)幌氮,CPU能夠在等待IO的時(shí)候做一些其他的事情。這個(gè)不一定就是磁盤(pán)IO胁澳。它也可以是網(wǎng)絡(luò)的IO该互,或者用戶輸入。通常情況下韭畸,網(wǎng)絡(luò)和磁盤(pán)的IO比CPU和內(nèi)存的IO慢的多宇智。
程序設(shè)計(jì)更簡(jiǎn)單
在單線程應(yīng)用程序中,如果你想編寫(xiě)程序手動(dòng)處理上面所提到的讀取和處理的順序胰丁,你必須記錄每個(gè)文件讀取和處理的狀態(tài)随橘。相反,你可以啟動(dòng)兩個(gè)線程锦庸,每個(gè)線程處理一個(gè)文件的讀取和操作机蔗。線程會(huì)在等待磁盤(pán)讀取文件的過(guò)程中被阻塞。在等待的時(shí)候甘萧,其他的線程能夠使用CPU去處理已經(jīng)讀取完的文件萝嘁。其結(jié)果就是,磁盤(pán)總是在繁忙地讀取不同的文件到內(nèi)存中扬卷。這會(huì)帶來(lái)磁盤(pán)和CPU利用率的提升牙言。而且每個(gè)線程只需要記錄一個(gè)文件,因此這種方式也很容易編程實(shí)現(xiàn)怪得。
程序響應(yīng)更快
將一個(gè)單線程應(yīng)用程序變成多線程應(yīng)用程序的另一個(gè)常見(jiàn)的目的是實(shí)現(xiàn)一個(gè)響應(yīng)更快的應(yīng)用程序咱枉。設(shè)想一個(gè)服務(wù)器應(yīng)用卑硫,它在某一個(gè)端口監(jiān)聽(tīng)進(jìn)來(lái)的請(qǐng)求。當(dāng)一個(gè)請(qǐng)求到來(lái)時(shí)蚕断,它去處理這個(gè)請(qǐng)求欢伏,然后再返回去監(jiān)聽(tīng)。
服務(wù)器的流程如下所述:
while(server is active){
listenforrequest
process
request
}
如果一個(gè)請(qǐng)求需要占用大量的時(shí)間來(lái)處理亿乳,在這段時(shí)間內(nèi)新的客戶端就無(wú)法發(fā)送請(qǐng)求給服務(wù)端颜懊。只有服務(wù)器在監(jiān)聽(tīng)的時(shí)候,請(qǐng)求才能被接收风皿。另一種設(shè)計(jì)是河爹,監(jiān)聽(tīng)線程把請(qǐng)求傳遞給工作者線程(worker?thread),然后立刻返回去監(jiān)聽(tīng)桐款。而工作者線程則能夠處理這個(gè)請(qǐng)求并發(fā)送一個(gè)回復(fù)給客戶端咸这。這種設(shè)計(jì)如下所述:
while(server is active){
listenforrequest
hand
request to worker thread
}
這種方式,服務(wù)端線程迅速地返回去監(jiān)聽(tīng)魔眨。因此媳维,更多的客戶端能夠發(fā)送請(qǐng)求給服務(wù)端。這個(gè)服務(wù)也變得響應(yīng)更快遏暴。
桌面應(yīng)用也是同樣如此侄刽。如果你點(diǎn)擊一個(gè)按鈕開(kāi)始運(yùn)行一個(gè)耗時(shí)的任務(wù),這個(gè)線程既要執(zhí)行任務(wù)又要更新窗口和按鈕朋凉,那么在任務(wù)執(zhí)行的過(guò)程中州丹,這個(gè)應(yīng)用程序看起來(lái)好像沒(méi)有反應(yīng)一樣。相反杂彭,任務(wù)可以傳遞給工作者線程(word?thread)墓毒。當(dāng)工作者線程在繁忙地處理任務(wù)的時(shí)候,窗口線程可以自由地響應(yīng)其他用戶的請(qǐng)求亲怠。當(dāng)工作者線程完成任務(wù)的時(shí)候所计,它發(fā)送信號(hào)給窗口線程。窗口線程便可以更新應(yīng)用程序窗口团秽,并顯示任務(wù)的結(jié)果主胧。對(duì)用戶而言,這種具有工作者線程設(shè)計(jì)的程序顯得響應(yīng)速度更快习勤。