内核aio_今天来说说令人让人傻傻分不清的BIO,NIO,AIO
- | 作者:新一、
- | 簡書:https://www.jianshu.com/u/b3263fc54bce
- | 知乎:https://www.zhihu.com/people/qing-ni-chi-you-zi-96
- | GitHub:https://github.com/JangYt?tab=repositories
- | 博客地址:https://blog.csdn.net/qq_41153943
一、概念
Java 中的 BIO、NIO和 AIO 理解為是 Java 語言對操作系統的各種 IO 模型的封裝。程序員在使用這些 API 的時候,不需要關心操作系統層面的知識,也不需要根據不同操作系統編寫不同的代碼。只需要使用Java的API就可以了。在講 BIO,NIO,AIO 之前先來回顧一下這樣幾個概念:同步與異步,阻塞與非阻塞。并且它們又可以排列組合成:同步阻塞、同步非阻塞、異步阻塞、異步非阻塞。
1、同步:指的是用戶進程觸發IO操作并等待或者輪詢的去查看IO操作是否就緒。比如肚子餓了去飯店吃飯,點好菜后一直問老板,飯好了沒有。
2、異步:異步指的是用戶進程觸發IO操作以后可以去做自己的事情,而當IO操作已經完成的時候會得到IO完成的通知,異步的特點就是通知。使用異步IO時,Java將IO讀寫委托給OS處理,需要將數據緩沖區地址和大小傳給OS。
對于通知調用者的三種方式,具體如下:
狀態:即監聽被調用者的狀態(輪詢),調用者需要每隔一定時間檢查一次,效率會很低。
通知:當被調用者執行完成后,發出通知告知調用者,無需消耗太多性能。
回調:與通知類似,當被調用者執行完成后,會調用調用者提供的回調函數。
總結來說,同步和異步的區別:請求發出后,是否需要等待結果,才能繼續執行其他操作。
3、阻塞:所謂阻塞方式的意思是指, 當試圖對該文件描述符進行讀寫時, 如果當時沒有東西可讀,或者暫時不可寫, 程序就進入等待狀態, 直到有東西可讀或者可寫為止。比如我們去吃飯的時候,飯一直沒好,那我們就處于阻塞的狀態了。
4、非阻塞:非阻塞狀態下, 如果沒有東西可讀, 或者不可寫, 讀寫函數馬上返回,而不會一直等待。比如我們吃飯的時候如果飯沒來的時候,我們可以打打游戲,看看電視,等著飯好,而不用一直傻傻的干等著。
所以:1、同步和異步是針對應用程序和內核的交互而言的。2、阻塞和非阻塞是針對于進程在訪問數據的時候,根據IO操作的就緒狀態來采取的不同方式,說白了是一種讀取或者寫入操作函數的實現方式,阻塞方式下讀取或者寫入函數將一直等待,而非阻塞方式下,讀取或者寫入函數會立即返回一個狀態值。 即同步和異步是目的,而阻塞和非阻塞是實現方式。一個IO操作其實分成了兩個步驟:發起IO請求和實際的IO操作。
而對于同步IO和異步IO的區別就在于實際的IO操作是否阻塞,如果實際的IO操作阻塞請求進程,那么就是同步IO。
同步和異步是針對應用程序和內核的交互而言的,同步指的是用戶進程觸發IO操作并等待或者輪詢的去查看IO操作是否就緒,而異步是指用戶進程觸發IO操作以后便開始做自己的事情,而當IO操作已經完成的時候會得到IO完成的通知。
而阻塞IO和非阻塞IO的區別就在于發起IO請求是否會被阻塞,如果阻塞直到完成那么就是阻塞IO,如果不阻塞,那么就是非阻塞IO。
阻塞和非阻塞是針對于進程在訪問數據的時候,根據IO操作的就緒狀態來采取的不同方式,說白了是一種讀取或者寫入操作函數的實現方式,阻塞方式下讀取或者寫入函數將一直等待,而非阻塞方式下,讀取或者寫入函數會立即返回一個狀態值。
所以,IO操作可以分為3類即我們這里要說的:BIO(Blocked IO:同步阻塞)、NIO(Non-Blocked IO:同步非阻塞)、AIO(Asynchronous IO:異步非阻塞)。
Java BIO (blocking IO):同步并阻塞,在JDK1.4出來之前,我們建立網絡連接的時候采用BIO模式,需要先在服務端啟動一個ServerSocket,然后在客戶端啟動Socket來對服務端進行通信,默認情況下服務端需要對每個請求建立一堆線程等待請求,而客戶端發送請求后,先咨詢服務端是否有線程相應,如果沒有則會一直等待或者遭到拒絕請求,如果有的話,客戶端會線程會等待請求結束后才繼續執行。所以如果這個連接不做任何事情會造成不必要的線程開銷,不過可以通過線程池機制改善。
Java NIO (non-blocking IO):同步非阻塞,服務器實現模式為一個請求一個線程,即客戶端發送的連接請求都會注冊到多路復用器上,多路復用器輪詢到連接有I/O請求時才啟動一個線程進行處理。
Java AIO(NIO.2) (Asynchronous IO) :異步非阻塞,服務器實現模式為一個有效請求一個線程,客戶端的I/O請求都是由OS先完成了再通知服務器應用去啟動線程進行處理。
另外還有一種異步阻塞IO,即經典的Reactor設計模式,叫的更多的其實是IO多路復用(IO Multiplexing)。多路復用是指使用一個線程來檢查多個文件描述符(Socket)的就緒狀態,比如調用select和poll函數,傳入多個文件描述符,如果有一個文件描述符就緒,則返回,否則阻塞直到超時。得到就緒狀態后進行真正的操作可以在同一個線程里執行,也可以啟動線程執行(比如使用線程池)。這樣在處理過多的連接時,只需要1個線程監控就緒狀態,對就緒的每個連接開一個線程處理就可以了,這樣需要的線程數大大減少,減少了內存開銷和上下文切換的CPU開銷。
舉個栗子:
我們在夜市買小吃的時候就經常有這樣的場景:比如我們在臭豆腐攤子那里點了份臭豆腐,但是人比較多,所以我們得排隊,輪到我們才能拿到臭豆腐,這個就是同步阻塞;但是有時候我們可以在臭豆腐這個點一份臭豆腐,然后跟老板說再去買份蛋炒飯過會過來拿,但是又不知道什么時候能好,畢竟臭豆腐熱乎的好吃啊,所以在等蛋炒飯的時候就過幾分鐘就去看看臭豆腐好了沒有,這種在炒飯攤和臭豆腐攤直接來回跑的就是同步非阻塞;還有一種就是我們已經是臭豆腐攤的老顧客了就跟老板說要一份臭豆腐,先去買蛋炒飯,臭豆腐好了打電話再過去拿,這就是異步阻塞;還有一種情況就是跟老板關系太好了,老板說你去買蛋炒飯吧,等臭豆腐好了我給你送過去,這個就是異步非阻塞了。
二、應用場景
BIO、NIO、AIO應用場景分析:
BIO方式適用于連接數目比較小且固定的架構,這種方式對服務器資源要求比較高,并發局限于應用中,JDK1.4以前的唯一選擇,但程序直觀簡單易理解。NIO方式適用于連接數目多且連接比較短(輕操作)的架構,比如聊天服務器,并發局限于應用中,編程比較復雜,JDK1.4開始支持。AIO方式使用于連接數目多且連接比較長(重操作)的架構,比如相冊服務器,充分調用OS參與并發操作,編程比較復雜,JDK7開始支持。
三、結尾
這里只是簡單的從概念和應用層面對java中的BIO、NIO、AIO進行解釋和分析,其實這里背后的原理涉及到了很多的底層的概念,比如網絡、操作系統等等,這里篇幅有限就不再過分展開說明,后面再細分進行展開,本文首發于gzh【1024筆記】,有興趣的可以移步gzh獲取海量資料。
總結
以上是生活随笔為你收集整理的内核aio_今天来说说令人让人傻傻分不清的BIO,NIO,AIO的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: creator qt 设置换行方式_wi
- 下一篇: batocera_batocera系统如