阻塞式和多執行緒 BIO 詳解 ServerSocket例項
1.什麼是IO
流是一種抽象概念,它代表了資料的無結構化傳遞。按照流的方式進行輸入輸出,資料被當成無結構的位元組或字元序列。從流中取得資料的操作稱為讀取,而向流中新增資料的操作稱為寫入。用來進行輸入輸出操作的流就稱為IO流。換句話說,IO流就是以流的方式進行輸入輸出。用通俗的話講,I就是in =進來=輸入流,O就是out=出去=輸出流,這裡的輸入輸出是以記憶體為參考物件,即輸入流可以理解為位元組從硬碟內跑到記憶體裡了, 硬碟-->記憶體 ,輸出流是位元組從記憶體跑到硬碟中 , 記憶體-->硬碟。以記憶體為參考物件,記憶體出去就是輸出流,要寫資料,進來記憶體就是輸入流,要讀資料。IO是計算機作業系統對資源讀和寫的操作,可以簡單理解為對資源的複製拷貝,只不過是目的地有所區別而已。初學者對IO可能會有點懵,輸入輸出到底是誰從哪裡輸入到哪裡,又輸出到哪裡,下面參考一張圖更加容易理解。
2.阻塞 非阻塞 同步 非同步
阻塞和非阻塞相對於資料而言阻塞:在讀取或者寫入資料的時候,一直需要等待作業系統(核心)準備資料,若資料已經就緒,IO開始進行讀或寫,否則,就處於阻塞等待狀態,等待資料的就緒,期間不能做其他事情,程式無法向下執行。
非阻塞:不論作業系統的資料是否已經準備好,程式都能繼續往下執行,不需等待資料的就緒。
同步和非同步是相對於IO事件而言,側重的方式不一樣
同步:在IO事件發生的時候,程式只能等待IO事件處理完畢,方可繼續往下執行
非同步:不關心IO事件是否處理完畢,讓作業系統去執行該事件的同時,繼續往下執行,等待該事件操作完畢時的一個通知,在往下執行的某個時候,會收到作業系統完成該事件的通知。
3.阻塞式IO 一般稱為BIO -- BlockedIO
使用jdk提供的ServerSocket Socket套接字可以模擬服務端與客戶端之間的通訊,或者基於此API,封裝伺服器和客戶端。在IO事件發生時,是處於阻塞狀態的。下面看程式碼
服務端程式碼
客戶端程式碼
執行結果:先執行服務端,再執行客戶端(執行main方法);
4.多執行緒式IO
由於阻塞式IO有阻塞,且每次只能為一個客戶端服務,多個客戶端連線需要依次等待,效率很低,資源利用也少。
如果使用多執行緒,每次客戶端連線之後,將任務放在新的執行緒去執行,那麼多個客戶端的任務執行互不干擾,可以併發的去執行。可以很大程式上解決單執行緒BIO的問題,這種BIO為多執行緒BIO
所以可以採用執行緒池的思想去解決,但是執行緒池在一定程式上限制了執行緒的數量,也會造成在海量併發情況下的等待阻塞,這種方式稱為偽非同步IO。
多執行緒IO 客戶端程式碼不變,服務端程式碼稍微改造一下即可。
new Thread().start(); 傳入執行的執行緒體,new Runable()實現run()方法
客戶端複製一下TcpClient類
執行結果: