摘要:選擇器核心類,能夠檢測多個(gè)注冊的通道上是否有事件發(fā)生,因此一個(gè)線程可以管理多個(gè)通道。標(biāo)記,記錄當(dāng)前的位置,可以通過恢復(fù)到的位置。而返回值記錄了包括,,集合和集合等。學(xué)習(xí)參考系列教程入門
一、NIO的核心部分
通道(channel):用于讀操作和寫操作,主要負(fù)責(zé)數(shù)據(jù)的“運(yùn)輸”。相當(dāng)于傳統(tǒng)IO中的stream,不過stream是單向的。
緩沖區(qū)(buffer):一個(gè)容器,用于存儲數(shù)據(jù)。
選擇器(selector):核心類,能夠檢測多個(gè)注冊的通道上是否有事件發(fā)生,因此一個(gè)線程可以管理多個(gè)通道。
使用NIO主要就是為了提高IO的速度
傳統(tǒng)IO是基于字節(jié)流和字符進(jìn)行操作的,而NIO是基于通道(channel)和緩沖區(qū)(buffer)進(jìn)行操作的,這樣一來數(shù)據(jù)的偏移操作非常方便。
傳統(tǒng)IO是阻塞的,如果發(fā)出IO請求后數(shù)據(jù)沒有就緒,會處于阻塞狀態(tài),而NIO通過通道操作數(shù)據(jù),因此一個(gè)通道無數(shù)據(jù)可讀,可以切換到另一個(gè)通道。
NIO有選擇器,因此單線程可以操作多個(gè)通道。
三、簡單的NIO讀和寫例子
從文件中讀取
與傳統(tǒng)IO不同的是,使用NIO從文件中讀取主要分為三步:
(1)從FileInputStream中獲取channel;
FileInputStream fin = new FileInputStream( "readandshow.txt" ); FileChannel fc = fin.getChannel();
(2)創(chuàng)建buffer;
ByteBuffer buffer = ByteBuffer.allocate( 1024 );
(3)將數(shù)據(jù)從channel讀到buffer中。
fc.read( buffer );
寫入文件
類似的,利用NIO寫入文件也分為三步:
(1)從FileInputStream中獲取channel;
FileOutputStream fout = new FileOutputStream( "writesomebytes.txt" ); FileChannel fc = fout.getChannel();
(2)創(chuàng)建一個(gè)緩沖區(qū)并在其中放入一些數(shù)據(jù);
ByteBuffer buffer = ByteBuffer.allocate( 1024 ); for (int i=0; i(3)將數(shù)據(jù)從buffer寫到通道中。
fc.write( buffer );四、buffer內(nèi)部細(xì)節(jié)flip()函數(shù)源碼
public final Buffer flip() { limit = position; position = 0; mark = -1; return this; }這里可以注意到limit,position和mark三個(gè)變量
五、選擇器
(1) capacity:表明可以儲存在緩沖區(qū)中的最大數(shù)據(jù)容量。
(2) position:下一個(gè)可插入的位置(寫buffer時(shí))或者下一個(gè)可讀的位置(讀buffer時(shí))。
(3) limit:最多能寫多少數(shù)據(jù)(寫buffer時(shí),相當(dāng)于capacity),可以讀多少數(shù)據(jù)(在從通道讀入緩沖區(qū)時(shí))。
(4) mark:標(biāo)記,記錄當(dāng)前position的位置,可以通過reset()恢復(fù)到mark的位置。selector的創(chuàng)建
Selector selector = Selector.open();
因?yàn)檫x擇器是用于管理通道的,因此需要將通道注冊到相應(yīng)的選擇器上
channel.configureBlocking(false); //使用selector必須保證channel是非阻塞的模式
SelectionKey key = channel.register(selector, Selectionkey.OP_READ);注意register的第二個(gè)參數(shù)表示對選擇器對什么事件感興趣。
而返回值記錄了包括channel,buffer,interest集合和ready集合等。通過selector選擇通道
可以使用select()函數(shù)進(jìn)行選擇,select()方法返回的int值表示有多少通道已經(jīng)就緒。selectedKeys()函數(shù)
一旦調(diào)用了select()方法,并且返回值表明有一個(gè)或更多個(gè)通道就緒了,然后可以通過調(diào)用selector的selectedKeys()方法,訪問“已選擇鍵集(selected key set)”中的就緒通道。這里的selectorKey的就是之前注冊到該selector的通道。
示例程序
Selector selector = Selector.open(); //開啟選擇器 channel.configureBlocking(false); //非阻塞模式 SelectionKey key = channel.register(selector, SelectionKey.OP_READ);//注冊 while(true) { int readyChannels = selector.select(); //選擇通道 if(readyChannels == 0) continue; Set selectedKeys = selector.selectedKeys(); //獲取通道 Iterator keyIterator = selectedKeys.iterator(); while(keyIterator.hasNext()) { SelectionKey key = keyIterator.next(); if(key.isAcceptable()) { // a connection was accepted by a ServerSocketChannel. } else if (key.isConnectable()) { // a connection was established with a remote server. } else if (key.isReadable()) { // a channel is ready for reading } else if (key.isWritable()) { // a channel is ready for writing } keyIterator.remove(); //需要自己移除處理完的通道 } }六、NIO和IO的使用場景NIO具備一定的優(yōu)點(diǎn),但并不是說傳統(tǒng)IO就一無是處
(1)在處理數(shù)據(jù)上,如果遇到逐行處理的情況,如:
Name: Anna Age: 25 Email: [email protected] Phone: 1234567890傳統(tǒng)的IO可以這樣寫:
BufferedReader reader = new BufferedReader(new InputStreamReader(input)); String nameLine = reader.readLine(); String ageLine = reader.readLine(); String emailLine = reader.readLine(); String phoneLine = reader.readLine();但如果使用NIO:
ByteBuffer buffer = ByteBuffer.allocate(48); int bytesRead = inChannel.read(buffer);你就不知道緩沖區(qū)內(nèi)是否剛好是一行數(shù)據(jù),這樣處理起來會比較麻煩。
(2)如果需要管理同時(shí)打開的成千上萬個(gè)連接,這些連接每次只是發(fā)送少量的數(shù)據(jù),例如聊天服務(wù)器,實(shí)現(xiàn)NIO的服務(wù)器可能是一個(gè)優(yōu)勢。
如果你需要維持許多打開的連接到其他計(jì)算機(jī)上,如P2P網(wǎng)絡(luò)中,使用一個(gè)多帶帶的線程來管理你所有出站連接,可能是一個(gè)優(yōu)勢。
但如果你有少量的連接使用非常高的帶寬,一次發(fā)送大量的數(shù)據(jù),也許典型的IO服務(wù)器實(shí)現(xiàn)可能非常契合。學(xué)習(xí)參考:http://ifeve.com/java-nio-all/ Java NIO 系列教程
https://www.ibm.com/developer... NIO入門
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/74999.html
摘要:是一個(gè)高性能事件驅(qū)動的異步的非堵塞的框架,用于建立等底層的連接,基于可以建立高性能的服務(wù)器。在中提供了兩套,一套是針對標(biāo)準(zhǔn)輸入輸出,另一套就是網(wǎng)絡(luò)編程。和是標(biāo)準(zhǔn)中的核心對象是對原中流的模擬,任何來源和目的數(shù)據(jù)都必須通過一個(gè)對象。 Netty是一個(gè)高性能 事件驅(qū)動的異步的非堵塞的IO(NIO)框架,用于建立TCP等底層的連接,基于Netty可以建立高性能的Http服務(wù)器。1、首先來復(fù)習(xí)下...
摘要:該線程在此期間不能再干任何事情了。線程通訊線程之間通過等方式通訊。選擇器傳統(tǒng)的模式會基于服務(wù)器會為每個(gè)客戶端請求建立一個(gè)線程由該線程單獨(dú)負(fù)貴處理一個(gè)客戶請求。 本文是對NIO知識的歸納與整理 1.阻塞與同步 1)阻塞(Block)和非租塞(NonBlock): 阻塞和非阻塞是進(jìn)程在訪問數(shù)據(jù)的時(shí)候,數(shù)據(jù)是否準(zhǔn)備就緒的一種處理方式,當(dāng)數(shù)據(jù)沒有準(zhǔn)備的時(shí)候阻塞:往往需要等待缞沖區(qū)中的數(shù)據(jù)準(zhǔn)備好...
摘要:表示的是兩個(gè),當(dāng)其中任意一個(gè)計(jì)算完并發(fā)編程之是線程安全并且高效的,在并發(fā)編程中經(jīng)常可見它的使用,在開始分析它的高并發(fā)實(shí)現(xiàn)機(jī)制前,先講講廢話,看看它是如何被引入的。電商秒殺和搶購,是兩個(gè)比較典型的互聯(lián)網(wǎng)高并發(fā)場景。 干貨:深度剖析分布式搜索引擎設(shè)計(jì) 分布式,高可用,和機(jī)器學(xué)習(xí)一樣,最近幾年被提及得最多的名詞,聽名字多牛逼,來,我們一步一步來擊破前兩個(gè)名詞,今天我們首先來說說分布式。 探究...
摘要:表示的是兩個(gè),當(dāng)其中任意一個(gè)計(jì)算完并發(fā)編程之是線程安全并且高效的,在并發(fā)編程中經(jīng)??梢娝氖褂?,在開始分析它的高并發(fā)實(shí)現(xiàn)機(jī)制前,先講講廢話,看看它是如何被引入的。電商秒殺和搶購,是兩個(gè)比較典型的互聯(lián)網(wǎng)高并發(fā)場景。 干貨:深度剖析分布式搜索引擎設(shè)計(jì) 分布式,高可用,和機(jī)器學(xué)習(xí)一樣,最近幾年被提及得最多的名詞,聽名字多牛逼,來,我們一步一步來擊破前兩個(gè)名詞,今天我們首先來說說分布式。 探究...
摘要:表示的是兩個(gè),當(dāng)其中任意一個(gè)計(jì)算完并發(fā)編程之是線程安全并且高效的,在并發(fā)編程中經(jīng)常可見它的使用,在開始分析它的高并發(fā)實(shí)現(xiàn)機(jī)制前,先講講廢話,看看它是如何被引入的。電商秒殺和搶購,是兩個(gè)比較典型的互聯(lián)網(wǎng)高并發(fā)場景。 干貨:深度剖析分布式搜索引擎設(shè)計(jì) 分布式,高可用,和機(jī)器學(xué)習(xí)一樣,最近幾年被提及得最多的名詞,聽名字多牛逼,來,我們一步一步來擊破前兩個(gè)名詞,今天我們首先來說說分布式。 探究...
閱讀 1240·2021-11-25 09:43
閱讀 1349·2021-09-26 09:55
閱讀 2410·2021-09-10 11:20
閱讀 3378·2019-08-30 15:55
閱讀 1454·2019-08-29 13:58
閱讀 1180·2019-08-29 12:36
閱讀 2353·2019-08-29 11:18
閱讀 3418·2019-08-26 11:47