天天看點

Java 并發/多線程教程(二)-多線程的優點資源的充分利用簡化程式設計響應的及時性

        本系列譯自jakob jenkov的Java并發多線程教程,個人覺得很有收獲。由于個人水準有限,不對之處還望矯正!

     盡管多線程有諸多的挑戰,但是多線程被廣泛使用的原因有以下幾點:

1、對資源的充分利用。

2、簡化程式設計

3、響應的及時性

       假設一個應用程式從本地檔案系統中讀取并處理一個檔案,讓我們來假設從硬碟讀取檔案需要5秒,處理檔案需要兩秒,那麼處理兩個檔案則需要:

5秒 讀取A檔案

2秒 處理A檔案

5秒 讀取B檔案

2秒 處理B檔案

共需14秒

當從硬碟讀取檔案的時候,CPU大部分時間用在等待從硬碟讀取資料,CPU 在等待的這段時間是非常空閑的,是可以被利用來做其他事情的,通過改變執行順序,CPU 可以被更好的利用。看下面的執行順序:

5秒  讀取A檔案

5秒 讀取B檔案+2秒處理A檔案

共需12秒

到CPU等待A檔案讀取的時候,開始讀取B檔案,當B檔案正在讀取的時候,CPU 開始處理A檔案,記住,當CPU 等待從硬碟讀取檔案的時候,CPU 幾乎是空閑的。

通常,CPU 在等待IO操作時,可以做其他的事情的,不光是磁盤IO,網絡IO也是一樣的

如果你打算用一個單線程的程式去處理上面的問題,你不得不時刻跟蹤每個檔案的讀取和處理狀态。而用多線程,你隻需要啟動兩個線程,而每個線程隻需負責單個檔案讀取和處理。這些線程會被blocked當等待從磁盤上讀取檔案,在等待的同時,另外的線程可以利用CPU 來處理它已經讀到的資料,這樣做的結果就是,磁盤一直處于繁忙的狀态,不斷地從磁盤讀取資料到記憶體中。這樣做,對于磁盤和CPU 的使用率得到提升,同時對于程式來說也更簡單,因為每個線程隻需去跟蹤一個檔案的讀取和處理狀态

将單線程轉變為多線程的另一個目的是更具有響應的及時性。假設一個服務端程程式在一個端口上監聽請求,當收到請求後,它對這個請求進行相應的處理,然後再傳回去監聽另外的請求。服務端程式如下:

while(server is active){

   listen for the request

   process request

}

如果這個請求花費了很長的時間去處理,那麼用戶端就不能在此期間發送任何請求到服務端,隻有當服務端處理完目前請求再次回到監聽時才能接受新的請求。另一種設計是監聽線程把接受到的請求交給工作線程(work  thread )然後立即傳回監聽。工作線程會對請求進行處理,并對用戶端傳回一個結果。這種設計模式如下:

listen for request

handle request to work thread

這種方式,監聽線程會很快繼續進行監聽,是以更多的用戶端可以發送更多的請求到服務端,服務端也變的更具響應性。這對桌面應用程式也是一樣的。