? ? ? ? 本系列譯自jakob jenkov的Java并發(fā)多線程教程,個人覺得很有收獲。由于個人水平有限,不對之處還望矯正!
? ? ?盡管多線程有諸多的挑戰(zhàn),但是多線程被廣泛使用的原因有以下幾點:
1、對資源的充分利用。
2、簡化程序設(shè)計
3、響應(yīng)的及時性
資源的充分利用
? ? ? ?假設(shè)一個應(yīng)用程序從本地文件系統(tǒng)中讀取并處理一個文件,讓我們來假設(shè)從硬盤讀取文件需要5秒,處理文件需要兩秒,那么處理兩個文件則需要:
5秒 讀取A文件
2秒 處理A文件
5秒 讀取B文件
2秒 處理B文件
共需14秒
當從硬盤讀取文件的時候,CPU大部分時間用在等待從硬盤讀取數(shù)據(jù),CPU 在等待的這段時間是非常空閑的,是可以被利用來做其他事情的,通過改變執(zhí)行順序,CPU 可以被更好的利用。看下面的執(zhí)行順序:
5秒 ?讀取A文件
5秒 讀取B文件+2秒處理A文件
2秒 處理B文件
共需12秒
到CPU等待A文件讀取的時候,開始讀取B文件,當B文件正在讀取的時候,CPU 開始處理A文件,記住,當CPU 等待從硬盤讀取文件的時候,CPU 幾乎是空閑的。
通常,CPU 在等待IO操作時,可以做其他的事情的,不光是磁盤IO,網(wǎng)絡(luò)IO也是一樣的
簡化程序設(shè)計
如果你打算用一個單線程的程序去處理上面的問題,你不得不時刻跟蹤每個文件的讀取和處理狀態(tài)。而用多線程,你只需要啟動兩個線程,而每個線程只需負責單個文件讀取和處理。這些線程會被blocked當?shù)却龔拇疟P上讀取文件,在等待的同時,另外的線程可以利用CPU 來處理它已經(jīng)讀到的數(shù)據(jù),這樣做的結(jié)果就是,磁盤一直處于繁忙的狀態(tài),不斷地從磁盤讀取數(shù)據(jù)到內(nèi)存中。這樣做,對于磁盤和CPU 的利用率得到提升,同時對于程序來說也更簡單,因為每個線程只需去跟蹤一個文件的讀取和處理狀態(tài)
響應(yīng)的及時性
將單線程轉(zhuǎn)變?yōu)槎嗑€程的另一個目的是更具有響應(yīng)的及時性。假設(shè)一個服務(wù)端程程序在一個端口上監(jiān)聽請求,當收到請求后,它對這個請求進行相應(yīng)的處理,然后再返回去監(jiān)聽另外的請求。服務(wù)端程序如下:
while(server is active){
? ?listen for the request
? ?process request
}
如果這個請求花費了很長的時間去處理,那么客戶端就不能在此期間發(fā)送任何請求到服務(wù)端,只有當服務(wù)端處理完當前請求再次回到監(jiān)聽時才能接受新的請求。另一種設(shè)計是監(jiān)聽線程把接受到的請求交給工作線程(work ?thread )然后立即返回監(jiān)聽。工作線程會對請求進行處理,并對客戶端返回一個結(jié)果。這種設(shè)計模式如下:
while(server is active){
listen for request
handle request to work thread
}
這種方式,監(jiān)聽線程會很快繼續(xù)進行監(jiān)聽,因此更多的客戶端可以發(fā)送更多的請求到服務(wù)端,服務(wù)端也變的更具響應(yīng)性。這對桌面應(yīng)用程序也是一樣的。