1、咱們先來看BIO的問題:編程
1 沒有數據緩衝區,I/O性能存在問題;網絡
2 沒有C或C++中的Channel概念,只有輸入和輸出流;併發
3 一般會致使通訊線程被長時間阻塞;異步
4 支持的字符集有限,硬件可移植性很差。性能
阻塞I/O模型:系統調用到數據包到達且被複制到應用進程的緩衝區中或者發生錯誤時才返回,在此期間一直會等待。優化
非阻塞I/O模型:輪詢檢查緩衝區有無數據的狀態。線程
I/O複用模型:Linux提供select/poll,偵測多個fd是否處於就緒狀態。同時還提供了一個epoll系統調用,一個基於事件驅動方式代替順序掃描,所以性能更高。指針
信號驅動模型:經過信號回調通知應用程序調用recvfrom來讀取數據server
異步I/O:和信號驅動I/O區別在於異步I/O模型由內核通知咱們I/O操做什麼時候已經完成。隊列
2、I/O多路複用
優點:系統開銷小,不須要建立新的額外進程或者線程,不須要維護進程和線程的運行,下降了系統維護工做量,節省系統資源。
應用場景:server同時處理多個處於監聽狀態或者多個鏈接狀態的套接字;
server須要同時處理多種網絡協議的套接字。
3、傳統BIO編程
下面先看下BIO通訊模型圖
首先有個Acceptor,負責監聽多個客戶端的鏈接,接收到鏈接請求後爲每一個客戶端建立一個新的線程進行鏈路處理,處理完成後,經過輸出流給客戶端發送響應,這就是經典的請求-應答模型。
該模型最大的問題就是缺少彈性伸縮能力,當客戶端併發訪問量增長後,服務端的線程個數和客戶端併發訪問數呈1:1的正比關係,因爲線程是Java虛擬機寶貴的系統資源,當線程數膨脹後,系統性能將急劇降低,隨着併發量持續增大,系統會發生線程堆棧溢出、建立新線程失敗等問題,並最終致使進程宕機或者僵死,不能對外提供服務。
爲了改進一線程一鏈接模型,後來又演進了一種經過線程池或者消息隊列實現1個或者多個線程處理N個客戶端的模型,因爲它的底層通訊機制依然使用同步阻塞I/O,因此被稱爲「僞異步」。
4、僞異步I/O編程
僞異步I/O通訊模型圖
僞異步I/O弊端分析
首先,當對Socket的輸入流進行讀取操做的時候,它會一直阻塞下去,直到發生以下三種事件:
有數據可讀;
可用數據已經讀取完畢;
發生空指針或者I/O異常。
這就意味着若是發送請求或者應答消息比較慢,或者網絡傳輸較慢時,讀取輸入流一方通訊線程就將長時間阻塞,在此期間,其餘接入消息只能在消息隊列中排隊。
所以,僞異步I/O實際上僅僅是對以前I/O線程模型的一個簡單優化,它沒法從根本上解決同步I/O致使的通訊線程阻塞問題。
OK,到這裏,阻塞I/O的相關知識就講解完畢,下節開始講NIO編程的相關知識和原理。