一、寫在開頭
很久沒更新嘍,最近build哥一直在忙著工作,忙著寫小說,都忘記學習自己的本職了,哈哈,不過現在正式迴歸!
我們繼續學習Java的IO相關內容,之前我們瞭解到,所謂的IO(Input/Output)就是計算機系統與外部裝置之間通訊的過程。
二、IO呼叫過程
接下來我們從應用呼叫的過程中來分析一下整個IO的執行過程。不過在此之前,我們需要簡單的瞭解一下整個作業系統的空間佈局。為了保證作業系統的穩定性和安全性,一個程序的地址空間劃分為使用者空間(User space) 和 核心空間(Kernel space ) 。
核心空間: 是作業系統核心所使用的空間,用來儲存底層核心程式碼、資料結構以及核心級別的系統呼叫。核心空間擁有比較高的許可權,比如檔案管理、程序通訊、記憶體管理等等。
使用者空間: 使用者級別的應用程式和服務分配的記憶體區域。它包含了應用程式的程式碼、資料和執行時堆疊。使用者空間與核心空間相對隔離,具有較低的許可權級別,不能直接訪問核心空間或硬體資源。
所以說,我們想要進行 IO 操作,一定是要依賴核心空間的能力。平常開發過程中接觸最多的就是磁碟 IO(讀寫檔案) 和 網路 IO(網路請求和響應)。
執行步驟:
- 應用程式發起IO請求;
- 系統核心接受到系統呼叫請求;
- 核心等待資料準備;
- 核心將資料從核心空間複製到使用者空間;
- IO輸出給應用程式。
三、IO常用模型
在UNIX系統中,我們所提到的IO模型一般是這四種:同步阻塞 I/O、同步非阻塞 I/O、I/O 多路複用、訊號驅動 I/O 和非同步 I/O。
不過,在日常使用中,我們常用的多為 BIO(Blocking I/O)
:同步阻塞 IO 模型、NIO (Non-blocking/New I/O)
:同步非阻塞 IO 模型、AIO (Asynchronous I/O)
:非同步 IO 模型。
3.1 BIO (Blocking I/O)
在傳統的IO中,多以這種同步阻塞的IO模型為主,這種模型下,程式發起IO請求後,處理執行緒處於阻塞狀態,直到請求的IO資料從核心空間複製到使用者空間。如下圖可以直觀的體現整個流程(圖源:沉默王二)。
如果發起IO的應用程式併發量不高的情況下,這種模型是沒問題的。但很明顯,當前的網際網路中,很多應用都有高併發IO請求的情況,這時就迫切的需要一款高效的IO模型啦。
3.2 NIO (Non-blocking/New I/O)
這種NIO模型,這個N既可以命名為NEW代表一種新型的IO模型,又可以理解為Non-Blocking,非阻塞之意。
Java NIO 是 Java 1.4 版本引入的,基於通道(Channel)和緩衝區(Buffer)進行操作,採用非阻塞式 IO 操作,允許執行緒在等待 IO 時執行其他任務。常見的 NIO 類有 ByteBuffer、FileChannel、SocketChannel、ServerSocketChannel 等。(圖源:深入拆解Tomcat & Jetty)
雖然在應用發起IO請求時,之多多次發起,無須阻塞。但在核心將資料複製到使用者空間時,還是會阻塞的,為了保證資料的準確性和系統的安全穩定。
3.3 I/O 多路複用模型
在同步非阻塞IO模型下,需要透過不斷的輪詢去檢查請求資料是否已經完成,這個過程是很耗CPU的。因此,便又誕生了I/O多路複用模型。
I/O 多路複用模型:使用作業系統提供的多路複用功能(如 select、poll、epoll 等),使得單個執行緒可以同時處理多個 I/O 事件。當某個連線上的資料準備好時,作業系統會通知應用程式。這樣,應用程式可以在一個執行緒中處理多個併發連線,而不需要為每個連線建立一個執行緒。(圖源:沉默王二)
3.4 AIO (Asynchronous I/O)
AIO 也就是 NIO 2。Java 7 中引入了 NIO 的改進版 NIO 2,它是非同步 IO 模型。非同步 IO 是基於事件和回撥機制實現的,也就是應用操作之後會直接返回,不會堵塞在那裡,當後臺處理完成,作業系統會通知相應的執行緒進行後續的操作。
總結
以上BIO、NIO、AIO三種常見的IO模型是Java面試中最常考的,大家一定要記住其各自的特點和作用。
- 阻塞 I/O:應用程式執行 I/O 操作時,會一直等待資料傳輸完成,期間無法執行其他任務。
- 非阻塞 I/O:應用程式執行 I/O 操作時,如果資料未準備好,立即返回錯誤狀態,不等待資料傳輸完成,可執行其他任務。
- 非同步 I/O:應用程式發起 I/O 操作後,核心負責資料傳輸過程,完成後通知應用程式。應用程式無需等待資料傳輸,可執行其他任務。