孫見福
先需要了解幾個概念:同步和異步,阻塞和非阻塞。
同步和異步
同步:進程觸發IO操作的時候,必須親自處理;你必須親自去銀行取錢。
異步:進程觸發IO操作的時候,可以不親自處理,它把操作委託給OS處理,委託的時候需要告知數據的地址和大小,然後自己去做別的事情,當IO操作結束後會得到通知;你把銀行卡給我,讓我幫你去銀行取錢,你需要告訴我銀行卡密碼和取多少錢,我取完了之後把錢給你。
總結:自己幹就是同步,別人幹就是異步。
阻塞和非阻塞
阻塞:進程觸發IO操作的時候,如果此時此時沒辦法讀或者寫,那麼進程就一直等待,直到讀寫結束;比如你去銀行ATM取錢,前面有人在排隊,那麼就要一直等待,直到你取完錢;
非阻塞:進程觸發IO操作的時候,如果此時此時沒辦法讀或者寫,那麼就先去做別的,等到有通知後,再繼續讀寫;比如你去銀行櫃檯取錢,人比較多,那就先領一個號,等著叫到號再去對應的窗口辦理業務;這裡不太恰當的是,我們等待的過程中,還得聽著叫號。
總結:我要等著不能做其他事就是阻塞,我不用等可以做其他事就是異步。
BIO、NIO、AIO
BIO:同步阻塞;一個請求過來,應用程序開了一個線程,等IO準備好,讀寫IO也是自己幹;但是為一個請求就啟動一個線程,開銷是比較大的,因為啟動和銷燬線程開銷很大,每個線程都要佔用內存,所以可以引入線程池,可以在一定程度上減少這些開銷;
NIO:同步非阻塞;不用等待IO準備,準備好了會通知,不過IO操作還是要自己幹;NIO是一種多路複用機制,利用單線程輪詢事件,Channel來決定做什麼,避免連接數多的時候,頻繁進行線程切換導致性能問題(Select階段阻塞)。
AIO:異步非阻塞;因為事情不是自己做,其實也沒有阻塞一說(都是非阻塞);AIO是在NIO的基礎上,引入異步通道的概念;NIO是採用輪詢的方式,不停地詢問stream中數據是否準備好了,準備好了就處理;AIO是向操作系統註冊IO監聽,操作系統完成IO操作了之後,主動通知,觸發響應的函數。
我將持續分享Java開發、架構設計、程序員職業發展等方面的見解,希望能得到你的關注。
會點代碼的大叔
這裡先回答你下BIO和NIO是什麼。
首先需要明白阻塞 非阻塞 同步 異步的概念,這裡引用下史蒂文斯的《UNIX網絡編程》中的幾張圖。
阻塞IO
圖中可以看到阻塞IO,一直阻塞在recvfrom方法調用上,直接數據複製完成
非阻塞IO
圖中可以看到非阻塞IO調用的recvfrom方法如果無數據直接返回,應用進程可以不斷輪詢是否有數據
IO複用
圖中可以看到IO複用,進程不再去輪詢獲取數據了,而是有select去查看數據是否準備好,準備好了,你再調用recvfrom方法去讀取數據
異步IO
異步IO,你發起系統調用,連數據都不用自己去讀取,而是操作系統直接給你複製到用戶空間,再回調你。
所以說同步和異步是針對用戶空間和內核空間交互而言的,而阻塞和非阻塞是針對用戶進程訪問數據而言的。強烈推薦下《UNIX網絡編程》。
BIO
java中的BIO是同步阻塞的。先看下服務端的例子
ServerSocket
這裡實例下ServerSocket的使用方法,可以看出一個連接過來就需要創建一個線程來處理連接,這裡可以使用線程池進行優化。
NIO
NIO的使用和注意的地方我都寫圖裡了。
NIO就是同步非阻塞,連接請求都會註冊到多路複用器上,多路複用器輪詢到連接有I/O請求時才進行處理,還是需要用戶自己去讀取數據,所以是同步的,但是不用阻塞在IO線程上,所以是非阻塞的。
學習NIO,還需要學習下 Buffer、Channel的使用。
Buffer
Buffer 可以理解為一個數組,可以進行數據的讀寫。在使用NIO的時候,我們的數據必須通過buffer和Channel進行交互。
Buffer 三個重要屬性:position、limit、capacity。
capacity:它代表這個緩衝區的容量,一旦設定就不可以更改。
position :初始值是 0,每寫入一個值,position 就自動加 1。讀也是類似的,每讀一個值,position 就自動加 1。寫操作切換讀操作的時候,可以調用flip,position 會歸零,這樣就可以從頭開始讀寫了。
limit:初始狀態下,limit 代表的是最大能寫入的數據,這個時候 limit 等於 capacity。調用flip後limit 等於 Buffer 中實際的數據大小,可以小於capacity。
Channel
Channel 通道,用於進行讀寫操作。一般使用channel.read(buffer) 和 channel.write(buffer)來讀寫數據。和流類似,但流是單向的,Channel是雙向的。
希望對你有所幫助,有幫助記得點贊哦!可以關注下,後面持續分享架構和Java的文章,謝謝!
淺析架構
BIO是一個連接一個線程。
NIO是一個請求一個線程。
AIO是一個有效請求一個線程。