想象壹下,壹個應用程序需要從本地文件系統中讀取和處理文件的情景。比方說,從磁盤讀取壹個文件需要5秒,處理壹個文件需要2秒。處理兩個文件則需要:
5秒讀取文件A
2秒處理文件A
5秒讀取文件B
2秒處理文件B
---------------------
總***需要14秒
從磁盤中讀取文件的時候,大部分的CPU時間用於等待磁盤去讀取數據。在這段時間裏,CPU非常的空閑。它可以做壹些別的事情。通過改變操作的順序,就能夠更好的使用CPU資源。看下面的順序:
5秒讀取文件A
5秒讀取文件B + 2秒處理文件A
2秒處理文件B
---------------------
總***需要12秒
CPU等待第壹個文件被讀取完。然後開始讀取第二個文件。當第二文件在被讀取的時候,CPU會去處理第壹個文件。記住,在等待磁盤讀取文件的時候,CPU大部分時間是空閑的。
總的說來,CPU能夠在等待IO的時候做壹些其他的事情。這個不壹定就是磁盤IO。它也可以是網絡的IO,或者用戶輸入。通常情況下,網絡和磁盤的IO比CPU和內存的IO慢的多。
程序設計更簡單
在單線程應用程序中,如果妳想編寫程序手動處理上面所提到的讀取和處理的順序,妳必須記錄每個文件讀取和處理的狀態。相反,妳可以啟動兩個線程,每
個線程處理壹個文件的讀取和操作。線程會在等待磁盤讀取文件的過程中被阻塞。在等待的時候,其他的線程能夠使用CPU去處理已經讀取完的文件。其結果就
是,磁盤總是在繁忙地讀取不同的文件到內存中。這會帶來磁盤和CPU利用率的提升。而且每個線程只需要記錄壹個文件,因此這種方式也很容易編程實現。
程序響應更快
將壹個單線程應用程序變成多線程應用程序的另壹個常見的目的是實現壹個響應更快的應用程序。設想壹個服務器應用,它在某壹個端口監聽進來的請求。當壹個請求到來時,它去處理這個請求,然後再返回去監聽。
服務器的流程如下所述:
while(server is active){
listen for request
process request
}
如果壹個請求需要占用大量的時間來處理,在這段時間內新的客戶端就無法發送請求給服務端。只有服務器在監聽的時候,請求才能被接收。另壹種設計是,
監聽線程把請求傳遞給工作者線程(worker
thread),然後立刻返回去監聽。而工作者線程則能夠處理這個請求並發送壹個回復給客戶端。這種設計如下所述:
while(server is active){
listen for request
hand request to worker thread
}
這種方式,服務端線程迅速地返回去監聽。因此,更多的客戶端能夠發送請求給服務端。這個服務也變得響應更快。
桌面應用也是同樣如此。如果妳點擊壹個按鈕開始運行壹個耗時的任務,這個線程既要執行任務又要更新窗口和按鈕,那麽在任務執行的過程中,這個應用程
序看起來好像沒有反應壹樣。相反,任務可以傳遞給工作者線程(word
thread)。當工作者線程在繁忙地處理任務的時候,窗口線程可以自由地響應其他用戶的請求。當工作者線程完成任務的時候,它發送信號給窗口線程。窗口
線程便可以更新應用程序窗口,並顯示任務的結果。對用戶而言,這種具有工作者線程設計的程序顯得響應速度更快。
壹個主頁 裏面有30個模塊 30個模塊分別讀取數據庫的數據
這個頁面 如果不用多線程,妳開打以後,會看到白頁,10秒以後 所有模塊壹瞬間看到
而多線程,打開頁面的第壹秒 頁面就打開了 這時候 頁面上只有3個模塊 然後 每過1秒 漫漫的 都顯示出來
用戶體驗好