Java NIO詳解

NIO含義

New I/O肢娘,原因在于相對于之前的I/O類庫是新增的辟癌。

由于之前老的I/O類庫是阻塞I/O,New I/O類庫的目標就是要讓Java支持非阻塞I/O弯囊,非阻塞I/O(Non-block I/O)更合適含滴。

SocketChannel和ServerSocketChannel

與Socket類和ServerSocket類相對應(yīng)诱渤,NIO也提供了SocketChannel和ServerSocketChannel兩種不同的套接字通道實現(xiàn)。這兩種新增的通道都支持阻塞和非阻塞兩種模式谈况。

低負載勺美、低并發(fā)的應(yīng)用程序可以選擇同步阻塞I/O以降低編程復(fù)雜度递胧;對于高負載、高并發(fā)的網(wǎng)絡(luò)應(yīng)用赡茸,需要使用NIO的非阻塞模式進行開發(fā)缎脾。

NIO類庫簡介

NIO彌補了原來同步阻塞I/O的不足,它在標準Java代碼中提供了高速的占卧、面向塊的I/O遗菠。

通過定義包含數(shù)據(jù)的類,以及通過以塊的形式處理這些數(shù)據(jù)华蜒,NIO不用使用本機代碼就可以利用低級優(yōu)化辙纬,這是原來的I/O包所無法做到的。

NIO類庫簡介 緩沖區(qū)Buffer

Buffer是一個對象友多,它包含一些要寫入或者要讀出的數(shù)據(jù)。

在NIO類庫中加入Buffer對象堤框,體現(xiàn)了新庫與原I/O的一個重要區(qū)別域滥。

在面向流的I/O中,可以將數(shù)據(jù)直接寫入或者將數(shù)據(jù)直接讀到Stream對象中蜈抓。

在NIO庫中启绰,所有數(shù)據(jù)都是用緩沖區(qū)處理的。在讀取數(shù)據(jù)時沟使,它是直接讀到緩沖區(qū)中的委可;在寫入數(shù)據(jù)時,寫入到緩沖區(qū)中腊嗡。任何時候訪問NIO中的數(shù)據(jù)着倾,都是通過緩沖區(qū)進行操作。

緩沖區(qū)實質(zhì)上是一個數(shù)組燕少。

緩沖區(qū)不僅僅是一個數(shù)組卡者,緩沖區(qū)提供了對數(shù)據(jù)的結(jié)構(gòu)化訪問以及維護讀寫位置(limit)等信息。

一個ByteBuffer提供了一組功能用于操作byte數(shù)組客们。

每一種Java基本類型(除了Boolean類型)都對應(yīng)有一種緩沖區(qū):

ByteBuffer:字節(jié)緩沖區(qū)

CharBuffer:字符緩沖區(qū)

ShortBuffer:短整型緩沖區(qū)

IntBuffer:整形緩沖區(qū)

LongBuffer:長整形緩沖區(qū)

FloatBuffer:浮點型緩沖區(qū)

DoubleBuffer:雙精度浮點型緩沖區(qū)

Java NIO詳解

每一個Buffer類都是Buffer接口的一個子實例崇决。除了ByteBuffer,每一個Buffer類都有完全一樣的操作底挫,只是它們所處理的數(shù)據(jù)類型不一樣恒傻。

因為大多數(shù)標準I/O操作都使用ByteBuffer,所以它在具有一般緩沖區(qū)的操作之外還提供了一些特有的操作建邓,以方便網(wǎng)絡(luò)讀寫盈厘。

NIO類庫簡介 通道Channel

Channel是一個通道,網(wǎng)絡(luò)數(shù)據(jù)通過Channel讀取和寫入官边。

通道與流的不同之處在于通道是雙向的扑庞,流只是在一個方向上移動(一個流必須是InputStream或者OutputStream的子類)譬重,而通道可以用于讀、寫或者二者同時進行罐氨。

因為Channel是全雙工的臀规,所以它可以比流更好地映射底層操作系統(tǒng)的API。特別是在UNIX網(wǎng)絡(luò)編程模型中栅隐,底層操作系統(tǒng)的通道都是全雙工的塔嬉,同時支持讀寫操作。

Java NIO詳解

自頂向下看租悄,前三層主要是Channel接口谨究,用于定義它的功能,后面是一些具體的功能類(抽象類)泣棋。從類圖可以看出胶哲,實際上Channel可以分為兩大類:用于網(wǎng)絡(luò)讀寫的SelectableChannel和用于文件操作的FileChannel。

ServerSocketChannel和SocketChannel都是SelectableChannel的子類

多路復(fù)用器Selector

多路復(fù)用器Selector是Java NIO編程的基礎(chǔ)

多路復(fù)用器提供選擇已就緒的任務(wù)的能力潭辈。

Selector會不斷地輪詢注冊在其上的Channel鸯屿,如果某個Channel上面發(fā)生讀或者寫事件,這個Channnel就處于就緒狀態(tài)把敢,會被Selector輪詢出來寄摆,然后通過SelectionKey可以獲取就緒Channel的集合,進行后續(xù)的I/O操作修赞。

一個多路復(fù)用器Selector可以同時輪詢多個Channel婶恼,由于JDK使用了epoll()代替?zhèn)鹘y(tǒng)的select實現(xiàn),所以它并沒有最大連接句柄1024/2048的限制柏副。這也就意味著只需要一個線程負責Selector的輪詢勾邦,就可以接入成千上萬的客戶端,這確實是個非常巨大的進步割择。

Java NIO詳解

下面用代碼簡單描述這個過程:

Java NIO詳解

使用NIO技術(shù)編寫TimeServer

Java NIO詳解
Java NIO詳解

使用NIO技術(shù)編寫TimeClient原理講解

時序圖:

Java NIO詳解

用代碼講解一下過程:

Java NIO詳解

使用NIO技術(shù)編寫TimeClient

Java NIO詳解
Java NIO詳解

注意

下面這種關(guān)閉socket的方法是錯誤的

Java NIO詳解

如果服務(wù)端沒有對這種情況進行處理會出現(xiàn)一下的錯誤:

Java NIO詳解

服務(wù)端最好是在讀取數(shù)據(jù)的時候做一下處理:

Java NIO詳解

優(yōu)勢

NIO編程的難度比同步阻塞BIO大很多检痰。

請注意以上的代碼中并沒有考慮“半包讀”和“半包寫”,如果加上這些锨推,代碼將會更加復(fù)雜铅歼。。

(1)客戶端發(fā)起的連接操作是異步的换可,可以通過在多路復(fù)用器注冊O(shè)P_CONNECT等待后續(xù)結(jié)果椎椰,不需要像之前的客戶端那樣被同步阻塞。

(2)SocketChannel的讀寫操作都是異步的沾鳄,如果沒有可讀寫的數(shù)據(jù)它不會同步等待慨飘,直接返回,這樣I/O通信線程就可以處理其他的鏈路,不需要同步等待這個鏈路可用瓤的。

(3)線程模型的優(yōu)化:由于JDK的Selector在Linux等主流操作系統(tǒng)上通過epoll實現(xiàn)休弃,它沒有連接句柄數(shù)的限制(只受限于操作系統(tǒng)的最大句柄數(shù)或者對單個進程的句柄限制),這意味著一個Selector線程可以同時處理成千上萬個客戶端連接圈膏,而且性能不會隨著客戶端的增加而線性下降塔猾。因此,它非常適合做高性能稽坤、高負載的網(wǎng)絡(luò)服務(wù)器丈甸。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市尿褪,隨后出現(xiàn)的幾起案子睦擂,更是在濱河造成了極大的恐慌,老刑警劉巖杖玲,帶你破解...
    沈念sama閱讀 218,640評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件顿仇,死亡現(xiàn)場離奇詭異,居然都是意外死亡摆马,警方通過查閱死者的電腦和手機臼闻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來今膊,“玉大人些阅,你說我怎么就攤上這事伞剑“呋#” “怎么了?”我有些...
    開封第一講書人閱讀 165,011評論 0 355
  • 文/不壞的土叔 我叫張陵黎泣,是天一觀的道長恕刘。 經(jīng)常有香客問我,道長抒倚,這世上最難降的妖魔是什么褐着? 我笑而不...
    開封第一講書人閱讀 58,755評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮托呕,結(jié)果婚禮上含蓉,老公的妹妹穿的比我還像新娘。我一直安慰自己项郊,他們只是感情好馅扣,可當我...
    茶點故事閱讀 67,774評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著着降,像睡著了一般差油。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,610評論 1 305
  • 那天蓄喇,我揣著相機與錄音发侵,去河邊找鬼。 笑死妆偏,一個胖子當著我的面吹牛刃鳄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播楼眷,決...
    沈念sama閱讀 40,352評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼铲汪,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了罐柳?” 一聲冷哼從身側(cè)響起掌腰,我...
    開封第一講書人閱讀 39,257評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎张吉,沒想到半個月后齿梁,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,717評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡肮蛹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,894評論 3 336
  • 正文 我和宋清朗相戀三年勺择,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片伦忠。...
    茶點故事閱讀 40,021評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡省核,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出昆码,到底是詐尸還是另有隱情气忠,我是刑警寧澤,帶...
    沈念sama閱讀 35,735評論 5 346
  • 正文 年R本政府宣布赋咽,位于F島的核電站旧噪,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏脓匿。R本人自食惡果不足惜淘钟,卻給世界環(huán)境...
    茶點故事閱讀 41,354評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望陪毡。 院中可真熱鬧米母,春花似錦、人聲如沸毡琉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽绊起。三九已至精拟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蜂绎。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評論 1 270
  • 我被黑心中介騙來泰國打工栅表, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人师枣。 一個月前我還...
    沈念sama閱讀 48,224評論 3 371
  • 正文 我出身青樓怪瓶,卻偏偏與公主長得像,于是被迫代替她去往敵國和親践美。 傳聞我的和親對象是個殘疾皇子洗贰,可洞房花燭夜當晚...
    茶點故事閱讀 44,974評論 2 355

推薦閱讀更多精彩內(nèi)容

  • NIO含義 New I/O,原因在于它相對于之前的I/O類庫是新增的陨倡。由于之前老的I/O類庫是阻塞I/O敛滋,New ...
    每天學(xué)點編程閱讀 5,559評論 0 6
  • 在java io中,核心概念為流(Stream)兴革,面向流的編程绎晃,一個流要么是輸出流,要么是輸入流杂曲,不能夠同時是輸出...
    Zak1閱讀 3,248評論 2 9
  • NIO原理 NIO與IO的區(qū)別 首先來講一下傳統(tǒng)的IO和NIO的區(qū)別庶艾,傳統(tǒng)的IO又稱BIO,即阻塞式IO擎勘,NIO就...
    faunjoe閱讀 419評論 0 0
  • 概述 BIO是面向字節(jié)流和字符流的咱揍,數(shù)據(jù)從流中順序獲取 NIO是面向通道和緩沖區(qū)的,數(shù)據(jù)總是從通道中讀到buffe...
    rockjh閱讀 697評論 0 0
  • 本文為原創(chuàng)文章棚饵,轉(zhuǎn)載請注明出處查看[Java]系列內(nèi)容請點擊:http://www.reibang.com/nb...
    大栗幾閱讀 309評論 0 5