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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

nio和bio的原理_Java的BIO,NIO和AIO的区别于演进

發布時間:2025/3/15 java 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 nio和bio的原理_Java的BIO,NIO和AIO的区别于演进 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

Java里面的IO模型種類較多,主要包括BIO,NIO和AIO,每個IO模型都有不一樣的地方,那么這些IO模型是如何演變呢,底層的原理又是怎樣的呢? 本文我們就來聊聊。

BIO

BIO全稱是Blocking IO,是JDK1.4之前的傳統IO模型,本身是同步阻塞模式,針對網絡通信都是一請求一應答的方式,雖然簡化了上層的應用開發,但在性能和可靠性方面存在著巨大瓶頸,試想一下如果每個請求都需要新建一個線程來專門處理,那么在高并發的場景下,機器資源很快就會被耗盡,當然,我們可以通過線程池來優化這種情況,但即使是這樣,仍然改變不了阻塞IO的根本問題,就是在IO執行的兩個階段都被block了。拿一個read操作來舉例子,在linux中,應用程序向linux發起read操作,會經歷兩個步驟:

第一個階段linux內核首先會把需要讀取的數據加載到操作系統內核的緩沖區中(Linux文件系統是緩存IO,也稱標準IO)

第二個階段應用程序拷貝內核里面的數據到自己的用戶空間中

如果是socket操作,類似也會經歷兩個步驟:

第一個階段:通常涉及等待網絡上的數據分組包到達,然后被復制到內核的緩沖區

第二個階段:把數據從內核緩沖區,從內核緩沖區拷貝到用戶進程的內存空間里面

同步阻塞IO之所以效率低下,就是因為在這兩個階段,用戶的線程或者進程都是阻塞的,期間雖然不占cpu資源,但也意味著該線程也不能再干其他事。有點站著茅坑不拉屎的感覺,自己暫時不用了,也不讓別人用。

圖示如下:

NIO

由于BIO的缺點,導致Java在JDK1.0至JDK3.0中,網絡通信模塊的性能一直是短板,所以很多人更傾向于使用C/C++開發高性能服務端。為了強化Java在服務端的市場,終于在JSR-51也就是JDK4.0的時候發布了Java NIO,可以支持非阻塞IO。并新增了java.nio的包,提供很多異步開發的API和類庫。

主要的類和接口如下:

(1)進行異步IO操作的緩沖區ByteBuffer

(2)進行異步IO操作的管道Pipe

(3)進行各種IO操作的Channel,主要包括ServerSocketChannel和SocketChannel

(4)實現非阻塞IO的多路復用器Selector

NIO主要有buffer、channel、selector三種技術的整合,通過零拷貝的buffer取得數據,每一個客戶端通過channel在selector(多路復用器)上進行注冊。服務端不斷輪詢channel來獲取客戶端的信息。channel上有connect,accept(阻塞)、read(可讀)、write(可寫)四種狀態標識。根據標識來進行后續操作。所以一個服務端可接收無限多的channel。不需要新開一個線程。大大提升了性能。

新的nio類庫,促進了異步非阻塞編程的發展和應用,但仍然有一些不足之處:

(1)沒有統一的文件屬性,例如讀寫權限

(2)api能力比較弱,例如目錄的及聯創建和遞歸遍歷,往往需要自己完成。

(3)底層操作系統的一些高級API無法使用

(4)所有的文件操作都是同步阻塞調用,在操作系統層面上并不是異步文件讀寫操作。

Java里面的NIO其實采用了多路復用的IO模式,多路復用的模式在Linux底層其實是采用了select,poll,epoll的機制,這種機制可以用單個線程同時監聽多個io端口,當其中任何一個socket的數據準備好了,就能返回通知用戶線程進行讀取操作,與阻塞IO阻塞的是每一個用戶的線程不一樣的地方是,多路復用只需要阻塞一個用戶線程即可,這個用戶線程通常我們叫它Selector,其實底層調用的是內核的select,這里面只要任何一個IO操作就緒,就可以喚醒select,然后交由用戶線程處理。用戶線程讀取數據這個過程仍然是阻塞的,多路復用技術只是在第一個階段可以變為非阻塞調用,但在第二個階段拷貝數據到用戶空間,其實還是阻塞的,多路復用技術的最大特點是使用一個線程就可以處理很多的socket連接,盡管性能上不一定提升,但支持并發能力卻大大增強了。

圖示如下:

AIO

AIO,其實是NIO的改進優化,也被稱為NIO2.0,在2011年7月,也就是JDK7的版本中發布,它主要提供了三個方面的改進:

(1)提供了能夠批量獲取文件屬性的api,通過SPI服務,使得這些API具有平臺無關性。

(2)提供了AIO的功能,支持基于文件的異步IO操作和網絡套接字的異步操作

(3)完成了JSR-51定義的通道功能等。

AIO 通過調用accept方法,一個會話接入之后再次調用(遞歸)accept方法,監聽下一次會話,讀取也不再阻塞,回調complete方法異步進行。不再需要selector 使用channel線程組來接收。

從NIO上面我們能看到,對于IO的兩個階段的阻塞,只是對于第一個階段有所改善,對于第二個階段在NIO里面仍然是阻塞的。而真正的理想的異步非阻塞IO(AAIO)要做的就是,將IO操作的兩個階段都全部交給內核系統完成,用戶線程只需要告訴內核,我要讀取一塊數據,請你幫我讀取,讀取完了放在我給你的地址里面,然后告訴我一聲就可以了。

AIO可以做到真正的異步的操作,但實現起來比較復雜,支持純異步IO的操作系統非常少,目前也就windows是IOCP技術實現了,而在Linux上,目前有很多開源的異步IO庫,例如libevent、libev、libuv,但基本都不是純的異步IO操作,底層還是是使用的epoll實現的。

圖示如下:

NIO與Netty

既然Java擁有了各種IO體系,那么為什么還會出現Netty這種框架呢?

Netty出現的主要原因,如下:

(1)Java NIO類庫和API繁雜眾多,使用麻煩。

(2)Java NIO封裝程度并不高,常常需要配合Java多線程編程來使用,這是因為NIO編程涉及到Reactor模式。

(3)Java NIO異常體系不完善,如客戶端面臨斷連,重連,網絡閃斷,半包讀寫,網絡阻塞,異常碼流等問題,雖然開發相對容易,但是可靠性和穩定性并不高。

(4)Java NIO本身的bug,修復較慢。

注意,真正的異步非阻塞io,是需要操作系統層面支持的,在windows上通過IOCP實現了真正的異步io,所以Java的AIO的異步在windows平臺才算真正得到了支持,而在Linux系統中,仍然用的是epoll模式,所以在Linux層面上的AIO,并不是真正的或者純的異步IO,這也是Netty里面為什么采用Java的NIO實現的,而并非是AIO,主要原因如下:

(1)AIO在linux上底層實現仍使用EPOLL,與NIO相同,因此在性能上沒有明顯的優勢

(2)Windows的AIO底層實現良好,但Netty的開發者并沒有把Windows作為主要使用平臺,所以優化考慮Linux

總結

本文主要介紹了Java里面IO模型的演變和發展,這也是Java在服務端領域大放異彩的一個重要原因,了解這些知識之后,我們再去學習高性能的Netty框架,將會更加容易

總結

以上是生活随笔為你收集整理的nio和bio的原理_Java的BIO,NIO和AIO的区别于演进的全部內容,希望文章能夠幫你解決所遇到的問題。

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