記-更加深刻理解Java IO
Java IO讀寫原理
- 在Java層面的應用開發離不開輸入流 Input 和 輸出流 Output 的處理,簡稱爲IO讀寫
- 用戶程序在進行IO讀寫操作的時候,離不開 read&write 的調用
- 需要注意的是IO讀寫並不是物理設備和內存之間的相互讀寫
- 以read系統爲代表的輸入流,是把數據從內核緩衝區複製到進程緩衝區
- 以write系統爲代表的輸出流,是把數據從進程緩衝區複製到內核緩衝區
- 內核緩衝區和磁盤之間的數據讀寫交換,由操作系統內核完成
Q:什麼是內核緩衝區?
- 操作系統的內核擁有對應的內核緩衝區
Q:什麼是進程緩衝區?
- 每一個進程擁有進程緩衝區
Q:緩衝區存在的目的?
- 減少頻繁的系統IO調用,提高性能
java IO讀寫流程
- 我們通常會使用到這樣的代碼
// client
OutputStream os = socket.getOutputStream();
os.write("xxx");
// server
InputStream is = socket.getInputStream();
is.read();
- client發起一次請求,os.write輸出流,把數據從進程緩衝區複製到內核緩衝區
- server接收請求,is.read把數據從內核緩衝區複製到進程緩衝區
關於同步和異步
- 同步(Synchronization)異步(Synchronization)
- 同步和異步是基於應用程序和操作系統處理IO所採用的方式
- 同步:一旦開始一個“過程”,調用者必須等到“過程”結束返回結果,才能繼續後續的行爲
- 異步:調用者會立即收到反饋,調用者可以進行後續操作而不會受到影響
- 同步IO :用戶空間線程主動發起IO請求,內核空間被動接受
- 異步IO :內核kernel是主動發起IO請求的一方,用戶線程是被動接受方
阻塞和非阻塞
- 阻塞(Block)非阻塞(Non-Block)
- 阻塞和非阻塞是進程在訪問數據的時候,數據是否處理就緒的一種處理方式
- 阻塞:需要等待數據處理完畢,才能進行後續操作
- 非阻塞:無論數據是否準備好,立即返回一個結果
- 阻塞IO : 用戶空間需要等待內核IO操作徹底完成。直到其返回一個結果。
- 非阻塞IO :內核IO操作無論是否完成,會立即反饋給用戶一個狀態值,用戶空間無需等待
IO模型
- 通過對同步、異步、阻塞和非阻塞有了一個初步的認識過後
- 方便我們更加透徹理解IO模型
BIO 即 同步阻塞IO (Block IO)
- 在Linux系統的Java進程中,默認所有的socket都是 blocking IO 即 阻塞IO
- 應用程序從發起IO調用開始直到系統返回,這段時間是阻塞的。返回成功後,應用程序纔會去處理後續邏輯
僞異步IO
- 通過設置socket實現non-blocking
- NIO模型中,應用程序開始調用,有以下兩種情況
- 在內核緩衝區沒有數據的情況下,系統調用會立即返回一個調用失敗的信息
- 在內核緩衝區有數據的情況下,是阻塞的,直到IO操作完成,返回成功結果
- 由於存在阻塞的情況,所以又稱爲僞異步IO
NIO—非阻塞IO
- 瞭解NIO之前需要明白:什麼是多路複用
- 多路複用模型
- 一個進程可以監視多個狀態(FD),一旦某個狀態就緒,內核發出反饋完成後續操作
- 典型的IO多路複用模型有 Java Selector、epoll
- 基本原理
- 非阻塞IO的實現基於select/epoll系統的調用,單個線程輪詢所負責的socket連接
- 當有socket連接的數據到達時,就返回這些都進行讀寫的連接
AIO (Asynchronous IO)
- 異步AIO,把IO讀寫操作完全交給操作系統
- 基本流程
- 用戶線程通過系統調用,告知kernel內核啓動某個IO操作,用戶線程返回。
- kernel內核在整個IO操作(包括數據準備,數據複製)完成後,通知用戶,用戶執行後續操作