日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人工智能 > ChatGpt >内容正文

ChatGpt

IO: BIO ? NIO ? AIO?

發布時間:2025/3/21 ChatGpt 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 IO: BIO ? NIO ? AIO? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

IO的方式通常分為幾種,同步阻塞的BIO、同步非阻塞的NIO、異步非阻塞的AIO。

一、BIO

?????在JDK1.4出來之前,我們建立網絡連接的時候采用BIO模式,需要先在服務端啟動一個ServerSocket,然后在客戶端啟動Socket來對服務端進行通信,默認情況下服務端需要對每個請求建立一堆線程等待請求,而客戶端發送請求后,先咨詢服務端是否有線程相應,如果沒有則會一直等待或者遭到拒絕請求,如果有的話,客戶端會線程會等待請求結束后才繼續執行。

二、NIO

????NIO本身是基于事件驅動思想來完成的,其主要想解決的是BIO的大并發問題在使用同步I/O的網絡應用中,如果要同時處理多個客戶端請求,或是在客戶端要同時和多個服務器進行通訊,就必須使用多線程來處理。也就是說,將每一個客戶端請求分配給一個線程來單獨處理。這樣做雖然可以達到我們的要求,但同時又會帶來另外一個問題。由于每創建一個線程,就要為這個線程分配一定的內存空間(也叫工作存儲器),而且操作系統本身也對線程的總數有一定的限制。如果客戶端的請求過多,服務端程序可能會因為不堪重負而拒絕客戶端的請求,甚至服務器可能會因此而癱瘓。

??? NIO基于Reactor,當socket有流可讀或可寫入socket時,操作系統會相應的通知應用程序進行處理,應用再將流讀取到緩沖區或寫入操作系統。? 也就是說,這個時候,已經不是一個連接就要對應一個處理線程了,而是有效的請求,對應一個線程,當連接沒有數據時,是沒有工作線程來處理的。

?? BIO與NIO一個比較重要的不同,是我們使用BIO的時候往往會引入多線程,每個連接一個單獨的線程;而NIO則是使用單線程或者只使用少量的多線程,每個連接共用一個線程。(IO多路復用技術)

????? NIO的最重要的地方是當一個連接創建后,不需要對應一個線程,這個連接會被注冊到多路復用器上面所以所有的連接只需要一個線程就可以搞定,當這個線程中的多路復用器進行輪詢的時候,發現連接上有請求的話,才開啟一個線程進行處理,也就是一個請求一個線程模式

??????在NIO的處理方式中,當一個請求來的話,開啟線程進行處理,可能會等待后端應用的資源(JDBC連接等),其實這個線程就被阻塞了,當并發上來的話,還是會有BIO一樣的問題。

  HTTP/1.1出現后,有了Http長連接,這樣除了超時和指明特定關閉的http header外,這個鏈接是一直打開的狀態的,這樣在NIO處理中可以進一步的進化,在后端資源中可以實現資源池或者隊列,當請求來的話,開啟的線程把請求和請求數據傳送給后端資源池或者隊列里面就返回(異步隊列),并且在全局的地方保持住這個現場(哪個連接的哪個請求等),這樣前面的線程還是可以去接受其他的請求,而后端的應用的處理只需要執行隊列里面的就可以了,這樣請求處理和后端應用是異步的.當后端處理完,到全局地方得到現場,產生響應,這個就實現了異步處理。

三、AIO

???? 與NIO不同,當進行讀寫操作時,只須直接調用API的read或write方法即可。這兩種方法均為異步的,對于讀操作而言,當有流可讀取時,操作系統會將可讀的流傳入read方法的緩沖區,并通知應用程序;對于寫操作而言,當操作系統將write方法傳遞的流寫入完畢時,操作系統主動通知應用程序。? 即可以理解為,read/write方法都是異步的,完成后會主動調用回調函數。? 在JDK1.7中,這部分內容被稱作NIO.2,主要在java.nio.channels包下增加了下面四個異步通道:

  • AsynchronousSocketChannel
  • AsynchronousServerSocketChannel
  • AsynchronousFileChannel
  • AsynchronousDatagramChannel

其中的read/write方法,會返回一個帶回調函數的對象,當執行完讀取/寫入操作后,直接調用回調函數。

BIO是一個連接一個線程。

NIO是一個請求一個線程。

AIO是一個有效請求一個線程。

先來個例子理解一下概念,以銀行取款為例:?

  • 同步 : 自己親自出馬持銀行卡到銀行取錢(使用同步IO時,Java自己處理IO讀寫);
  • 異步 : 委托一小弟拿銀行卡到銀行取錢,然后給你(使用異步IO時,Java將IO讀寫委托給OS處理,需要將數據緩沖區地址和大小傳給OS(銀行卡和密碼),OS需要支持異步IO操作API);
  • 阻塞 : ATM排隊取款,你只能等待(使用阻塞IO時,Java調用會一直阻塞到讀寫完成才返回);
  • 非阻塞 : 柜臺取款,取個號,然后坐在椅子上做其它事,等號廣播會通知你辦理,沒到號你就不能去,你可以不斷問大堂經理排到了沒有,大堂經理如果說還沒到你就不能去(使用非阻塞IO時,如果不能讀寫Java調用會馬上返回,當IO事件分發器會通知可讀寫時再繼續進行讀寫,不斷循環直到讀寫完成

Java對BIO、NIO、AIO的支持:

  • Java BIO : 同步并阻塞,服務器實現模式為一個連接一個線程,即客戶端有連接請求時服務器端就需要啟動一個線程進行處理,如果這個連接不做任何事情會造成不必要的線程開銷,當然可以通過線程池機制改善。

  • Java NIO : 同步非阻塞,服務器實現模式為一個請求一個線程,即客戶端發送的連接請求都會注冊到多路復用器上,多路復用器輪詢到連接有I/O請求時才啟動一個線程進行處理。

  • Java AIO(NIO.2) : 異步非阻塞,服務器實現模式為一個有效請求一個線程,客戶端的I/O請求都是由OS先完成了再通知服務器應用去啟動線程進行處理,

BIO、NIO、AIO適用場景分析:

  • BIO方式適用于連接數目比較小且固定的架構,這種方式對服務器資源要求比較高,并發局限于應用中,JDK1.4以前的唯一選擇,但程序直觀簡單易理解。

  • NIO方式適用于連接數目多且連接比較短(輕操作)的架構,比如聊天服務器,并發局限于應用中,編程比較復雜,JDK1.4開始支持。

  • AIO方式使用于連接數目多且連接比較長(重操作)的架構,比如相冊服務器,充分調用OS參與并發操作,編程比較復雜,JDK7開始支持。

另外,I/O屬于底層操作,需要操作系統支持,并發也需要操作系統的支持,所以性能方面不同操作系統差異會比較明顯。

在高性能的I/O設計中,有兩個比較著名的模式Reactor和Proactor模式,其中Reactor模式用于同步I/O,而Proactor運用于異步I/O操作。

?一般來說I/O模型可以分為:同步阻塞,同步非阻塞,異步阻塞,異步非阻塞IO

1,同步和異步是針對應用程序和內核的交互而言的。?同步/異步是在時間上強調處理事情的結果/機會成本的兩種處理策略;強調結果意味著對結果的迫不急待,不過結果是正確的還是錯誤的,反正你要立即給我一個結果響應;強調時間機會成本意味著對等待結果浪費的時間極其難接受,而對結果并不是那么急切,暫時不管結果(讓處理方處理完主動通知結果/自己空閑的時候主動去獲取結果)轉而去處理其他事情

2,阻塞和非阻塞是針對于進程在訪問數據的時候,根據IO操作的就緒狀態來采取的不同方式,說白了是一種讀取或者寫入操作函數的實現方式,阻塞方式下讀取或者寫入函數將一直等待,而非阻塞方式下,讀取或者寫入函數會立即返回一個狀態值。

3,同步/異步是宏觀上(進程間通訊,通常表現為網絡IO的處理上),阻塞/非阻塞是微觀上(進程內數據傳輸,通常表現為對本地IO的處理上);阻塞和非阻塞是同步/異步的表現形式

由上描述基本可以總結一句簡短的話,同步和異步是目的,阻塞和非阻塞是實現方式。?

?

下面我們再來理解組合方式的IO類型,就好理解多了。?

同步阻塞IO(JAVA BIO):?
??? 同步并阻塞,服務器實現模式為一個連接一個線程,即客戶端有連接請求時服務器端就需要啟動一個線程進行處理,如果這個連接不做任何事情會造成不必要的線程開銷,當然可以通過線程池機制改善。?

同步非阻塞IO(Java NIO) : 同步非阻塞,服務器實現模式為一個請求一個線程,即客戶端發送的連接請求都會注冊到多路復用器上,多路復用器輪詢到連接有I/O請求時才啟動一個線程進行處理。用戶進程也需要時不時的詢問IO操作是否就緒,這就要求用戶進程不停的去詢問。?

異步阻塞IO(Java NIO):??
?? 此種方式下是指應用發起一個IO操作以后,不等待內核IO操作的完成,等內核完成IO操作以后會通知應用程序,這其實就是同步和異步最關鍵的區別,同步必須等待或者主動的去詢問IO是否完成,那么為什么說是阻塞的呢?因為此時是通過select系統調用來完成的,而select函數本身的實現方式是阻塞的,而采用select函數有個好處就是它可以同時監聽多個文件句柄(如果從UNP的角度看,select屬于同步操作。因為select之后,進程還需要讀寫數據),從而提高系統的并發性!??


(Java AIO(NIO.2))異步非阻塞IO:??
?? 在此種模式下,用戶進程只需要發起一個IO操作然后立即返回,等IO操作真正的完成以后,應用程序會得到IO操作完成的通知,此時用戶進程只需要對數據進行處理就好了,不需要進行實際的IO讀寫操作,因為真正的IO讀取或者寫入操作已經由內核完成了。????

BIO、NIO、AIO適用場景分析:?

??? BIO方式適用于連接數目比較小且固定的架構,這種方式對服務器資源要求比較高,并發局限于應用中,JDK1.4以前的唯一選擇,但程序直觀簡單易理解。?

??? NIO方式適用于連接數目多且連接比較短(輕操作)的架構,比如聊天服務器,并發局限于應用中,編程比較復雜,JDK1.4開始支持。?

??? AIO方式使用于連接數目多且連接比較長(重操作)的架構,比如相冊服務器,充分調用OS參與并發操作,編程比較復雜,JDK7開始支持。?

搞清楚了以上概念以后,我們再回過頭來看看,Reactor模式和Proactor模式。??
?

?首先來看看Reactor模式,Reactor模式應用于同步I/O的場景。我們分別以讀操作和寫操作為例來看看Reactor中的具體步驟:??
讀取操作:??
1. 應用程序注冊讀就緒事件和相關聯的事件處理器??
??
2. 事件分離器等待事件的發生??
??
3. 當發生讀就緒事件的時候,事件分離器調用第一步注冊的事件處理器??
??
4. 事件處理器首先執行實際的讀取操作,然后根據讀取到的內容進行進一步的處理??
??
寫入操作類似于讀取操作,只不過第一步注冊的是寫就緒事件。??
???
??
下面我們來看看Proactor模式中讀取操作和寫入操作的過程:??
讀取操作:??
1. 應用程序初始化一個異步讀取操作,然后注冊相應的事件處理器,此時事件處理器不關注讀取就緒事件,而是關注讀取完成事件,這是區別于Reactor的關鍵。??
??
2. 事件分離器等待讀取操作完成事件??
??
3. 在事件分離器等待讀取操作完成的時候,操作系統調用內核線程完成讀取操作(異步IO都是操作系統負責將數據讀寫到應用傳遞進來的緩沖區供應用程序操作,操作系統扮演了重要角色),并將讀取的內容放入用戶傳遞過來的緩存區中。這也是區別于Reactor的一點,Proactor中,應用程序需要傳遞緩存區。??
??
4. 事件分離器捕獲到讀取完成事件后,激活應用程序注冊的事件處理器,事件處理器直接從緩存區讀取數據,而不需要進行實際的讀取操作。??
??
Proactor中寫入操作和讀取操作,只不過感興趣的事件是寫入完成事件。??
??
從上面可以看出,Reactor和Proactor模式的主要區別就是真正的讀取和寫入操作是有誰來完成的,Reactor中需要應用程序自己讀取或者寫入數據,而Proactor模式中,應用程序不需要進行實際的讀寫過程,它只需要從緩存區讀取或者寫入即可,操作系統會讀取緩存區或者寫入緩存區到真正的IO設備.??
???
????????? 綜上所述,同步和異步是相對于應用和內核的交互方式而言的,同步 需要主動去詢問,而異步的時候內核在IO事件發生的時候通知應用程序,而阻塞和非阻塞僅僅是系統在調用系統調用的時候函數的實現方式而已。??



如果你想吃一份宮保雞丁蓋飯:?

同步阻塞:你到飯館點餐,然后在那等著,還要一邊喊:好了沒啊!?

同步非阻塞:在飯館點完餐,就去遛狗了。不過溜一會兒,就回飯館喊一聲:好了沒啊!?

異步阻塞:遛狗的時候,接到飯館電話,說飯做好了,讓您親自去拿。?

異步非阻塞:飯館打電話說,我們知道您的位置,一會給你送過來,安心遛狗就可以了。
?

“一個IO操作其實分成了兩個步驟:發起IO請求和實際的IO操作。?
同步IO和異步IO的區別就在于第二個步驟是否阻塞,如果實際的IO讀寫阻塞請求進程,那么就是同步IO。?
阻塞IO和非阻塞IO的區別在于第一步,發起IO請求是否會被阻塞,如果阻塞直到完成那么就是傳統的阻塞IO,如果不阻塞,那么就是非阻塞IO。?

同步和異步是針對應用程序和內核的交互而言的,同步指的是用戶進程觸發IO操作并等待或者輪詢的去查看IO操作是否就緒,而異步是指用戶進程觸發IO操作以后便開始做自己的事情,而當IO操作已經完成的時候會得到IO完成的通知。而阻塞和非阻塞是針對于進程在訪問數據的時候,根據IO操作的就緒狀態來采取的不同方式,說白了是一種讀取或者寫入操作函數的實現方式,阻塞方式下讀取或者寫入函數將一直等待,而非阻塞方式下,讀取或者寫入函數會立即返回一個狀態值。?
所以,IO操作可以分為3類:同步阻塞(即早期的IO操作)、同步非阻塞(NIO)、異步(AIO)。?
同步阻塞:?
在此種方式下,用戶進程在發起一個IO操作以后,必須等待IO操作的完成,只有當真正完成了IO操作以后,用戶進程才能運行。JAVA傳統的IO模型屬于此種方式。?

同步非阻塞:?
在此種方式下,用戶進程發起一個IO操作以后邊可返回做其它事情,但是用戶進程需要時不時的詢問IO操作是否就緒,這就要求用戶進程不停的去詢問,從而引入不必要的CPU資源浪費。其中目前JAVA的NIO就屬于同步非阻塞IO。?
異步:?
此種方式下是指應用發起一個IO操作以后,不等待內核IO操作的完成,等內核完成IO操作以后會通知應用程序?!?


最后,幾篇解釋的不錯的文章:

BIO NIO AIO

NIO.2 入門,第 1 部分: 異步通道 API

使用異步 I/O 大大提高應用程序的性能

?

?

總結

以上是生活随笔為你收集整理的IO: BIO ? NIO ? AIO?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。