成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

Java NIO 基礎(chǔ)(一)

hizengzeng / 1585人閱讀

摘要:通過(guò)協(xié)議向網(wǎng)絡(luò)讀寫(xiě)數(shù)據(jù)通過(guò)協(xié)議向網(wǎng)絡(luò)讀寫(xiě)數(shù)據(jù)以一個(gè)服務(wù)器的形式,監(jiān)聽(tīng)到來(lái)的連接,對(duì)每個(gè)連接建立一個(gè)。

Java NIO 教程 NIO是什么?

它是Java1.4之后出現(xiàn)的IO API,與傳統(tǒng)IO和網(wǎng)絡(luò)API不同,具有非阻塞的特點(diǎn)。

在BIO中我們使用字節(jié)流和字符流。NIO中我們使用channel和buffer。數(shù)據(jù)總是從一個(gè)channel中讀取到buffer中,或者從buffer中寫(xiě)入到channel中。

NIO的意思是一個(gè)線程可以讓一個(gè)channel將數(shù)據(jù)讀取到buffer中,與此同時(shí),這個(gè)線程還可以做其他的事情,線程可以等到數(shù)據(jù)全部進(jìn)入buffer之后再處理數(shù)據(jù),從buffer中寫(xiě)入線程也是一樣的。

selector:選擇器是一個(gè)NIO當(dāng)中的概念,指的是一個(gè)對(duì)象,能監(jiān)視多個(gè)channel發(fā)生的事件(如連接建立,數(shù)據(jù)到達(dá)等)。因此,一個(gè)單線程可以監(jiān)視多個(gè)channel的數(shù)據(jù)。

Java NIO 總覽

Java NIO的三個(gè)核心基礎(chǔ)組件,

Channels

Buffers

Selectors

其余的諸如Pipe,F(xiàn)ileLcok都是在使用以上三個(gè)核心組件時(shí)幫助更好使用的工具類(lèi)。

Channels和Buffers的關(guān)系

所有的IO操作在NIO中都是以Channel開(kāi)始的。一個(gè)Channel就像一個(gè)流。從Channel中,數(shù)據(jù)可以被讀取到buffer里,也可以從buffer里寫(xiě)到Channel中。

基本的Channel實(shí)現(xiàn)有以下這些:

FileChannel

DatagramChannel

SocketChannel

ServerSocketChannel

涵蓋了UDP,TCP以及文件的IO操作。

核心的buffer實(shí)現(xiàn)有這些

ByteBuffer

CharBuffer

DoubleBuffer

FloatBuffer

IntBuffer

LongBuffer

ShortBuffer

涵蓋了所有的基本數(shù)據(jù)類(lèi)型(4類(lèi)8種,除了Boolean)。也有其他的buffer如MappedByteBuffer,此處不講。

selectors

selector允許一個(gè)線程來(lái)監(jiān)視多個(gè)Channel,這在當(dāng)你的應(yīng)用建立了多個(gè)連接,但是每個(gè)連接吞吐量都較小的時(shí)候是可行的。例如:一個(gè)聊天服務(wù)器。圖為一個(gè)線程使用selector處理三個(gè)channel。

要使用一個(gè)Selector,你要先注冊(cè)這個(gè)selector的Channels。然后你調(diào)用selector的select()方法。這個(gè)方法會(huì)阻塞,直到它注冊(cè)的channels當(dāng)中有一個(gè)準(zhǔn)備好了的事件發(fā)生了。當(dāng)select()方法返回的時(shí)候,線程可以處理這些事件,如新的連接的到來(lái),數(shù)據(jù)收到了等。

NIO Channels

NIO channel和流很近似但是也有一些不同。

你既可以讀取也可以寫(xiě)入到channel,流只能讀取或者寫(xiě)入,inputStream和outputStream。

channel可以異步地讀和寫(xiě)。

channel永遠(yuǎn)都是從一個(gè)buffer中讀或者寫(xiě)入到一個(gè)buffer中去。

channel的實(shí)現(xiàn)

以下是NIO中最重要的幾個(gè)channel的實(shí)現(xiàn)。

FileChannel 向文件當(dāng)中讀寫(xiě)數(shù)據(jù)。

DatagramChannel 通過(guò)UDP協(xié)議向網(wǎng)絡(luò)讀寫(xiě)數(shù)據(jù)

SocketChannel 通過(guò)TCP協(xié)議向網(wǎng)絡(luò)讀寫(xiě)數(shù)據(jù)

ServerSocketChannel 以一個(gè)web服務(wù)器的形式,監(jiān)聽(tīng)到來(lái)的TCP連接,對(duì)每個(gè)連接建立一個(gè)SocketChannel。

一個(gè)簡(jiǎn)單的channel例子

使用一個(gè)FileChannel將數(shù)據(jù)讀入一個(gè)buffer

     RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw");
    FileChannel inChannel = aFile.getChannel();

    ByteBuffer buf = ByteBuffer.allocate(48);

    int bytesRead = inChannel.read(buf);
    while (bytesRead != -1) {

      System.out.println("Read " + bytesRead);
      buf.flip();

      while(buf.hasRemaining()){
          System.out.print((char) buf.get());
      }

      buf.clear();
      bytesRead = inChannel.read(buf);
    }
    aFile.close();

buf.flip()的意思是讀寫(xiě)轉(zhuǎn)換,首先你讀入一個(gè)buffer,然后你flip,轉(zhuǎn)換讀寫(xiě),然后再?gòu)腷uffer中讀出,buffer的操作接下來(lái)會(huì)講。

NIO buffer

NIO buffer在與NIO Channel交互時(shí)使用,數(shù)據(jù)從channel中讀取出來(lái)放入buffer,或者從buffer中讀取出來(lái)寫(xiě)入channel。

buffer就是一塊內(nèi)存,你可以寫(xiě)入數(shù)據(jù),并且在之后讀取它。這塊內(nèi)存被包裝成NIO buffer對(duì)象,它提供了一些方法來(lái)讓你更簡(jiǎn)單地操作內(nèi)存。

buffer的基本使用

使用buffer讀寫(xiě)數(shù)據(jù)基本上分為以下4部操作:

將數(shù)據(jù)寫(xiě)入buffer

調(diào)用buffer.flip()

將數(shù)據(jù)從buffer中讀取出來(lái)

調(diào)用buffer.clear()或者buffer.compact()

在寫(xiě)buffer的時(shí)候,buffer會(huì)跟蹤寫(xiě)入了多少數(shù)據(jù),需要讀buffer的時(shí)候,需要調(diào)用flip()來(lái)將buffer從寫(xiě)模式切換成讀模式,讀模式中只能讀取寫(xiě)入的數(shù)據(jù),而非整個(gè)buffer。

當(dāng)數(shù)據(jù)都讀完了,你需要清空buffer以供下次使用,可以有2種方法來(lái)操作:

調(diào)用clear()

調(diào)用compact()

區(qū)別:clear方法清空整個(gè)buffer,compact方法只清除你已經(jīng)讀取的數(shù)據(jù),未讀取的數(shù)據(jù)會(huì)被移到buffer的開(kāi)頭,此時(shí)寫(xiě)入數(shù)據(jù)會(huì)從當(dāng)前數(shù)據(jù)的末尾開(kāi)始。

一個(gè)簡(jiǎn)單的buffer使用例子:

RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw");
FileChannel inChannel = aFile.getChannel();

//創(chuàng)建一個(gè)容量為48的ByteBuffer
ByteBuffer buf = ByteBuffer.allocate(48);

int bytesRead = inChannel.read(buf); //從channel中讀(取數(shù)據(jù)然后寫(xiě))入buffer
//下面是讀取buffer
while (bytesRead != -1) {

      buf.flip();                      //轉(zhuǎn)換buffer為讀模式

     while(buf.hasRemaining()){
          System.out.print((char) buf.get()); // 一次讀取一個(gè)byte
      }

  buf.clear();                         //清空buffer準(zhǔn)備下一次寫(xiě)入
  bytesRead = inChannel.read(buf);    
}
aFile.close();
buffer的Capacity,Position和Limit

buffer有3個(gè)屬性需要熟悉以理解buffer的工作原理:

容量(Capacity):緩沖區(qū)能夠容納的數(shù)據(jù)元素的最大數(shù)量。容量在緩沖區(qū)創(chuàng)建時(shí)被設(shè)定,并且永遠(yuǎn)不能被改變。

上界(Limit):寫(xiě)模式中等價(jià)于buffer的大小,即capacity;讀模式中為當(dāng)前緩沖區(qū)中一共有多少數(shù)據(jù),即可讀的最大位置。這意味著當(dāng)調(diào)用filp()方法切換成讀模式時(shí),limit的值變成position的值,而position重新指向0.

位置(Position):下一個(gè)要被讀或?qū)懙脑氐奈恢?。初始化?,buffer滿(mǎn)時(shí),position最大值為capacity-1。切換成讀模式的時(shí)候,position指向0。Position會(huì)自動(dòng)由相應(yīng)的 get( )和 put( )函數(shù)更新。

position和limit的值在讀/寫(xiě)模式中是不一樣的。
capacity的值永遠(yuǎn)表示buffer的大小。

下圖解釋了在讀/寫(xiě)模式中Capacity,Position和Limit的意思。

buffer的種類(lèi)

Java NIO中有以下這些buffer種類(lèi):

ByteBuffer

MappedByteBuffer //比較特殊,會(huì)在以后講解

CharBuffer

DoubleBuffer

FloatBuffer

IntBuffer

LongBuffer

ShortBuffer

創(chuàng)建一個(gè)buffer

獲得一個(gè)buffer 之前必須先分配一塊內(nèi)存,每個(gè)buffer類(lèi)都有一個(gè)靜態(tài)方法allocate() 來(lái)做這件事。

下例為創(chuàng)建一個(gè)容量為48byte的ByteBuffer:
ByteBuffer buf = ByteBuffer.allocate(48);

創(chuàng)建一個(gè)1024個(gè)字符的CharBuffer
CharBuffer buf = CharBuffer.allocate(1024);

將數(shù)據(jù)寫(xiě)入buffer

寫(xiě)入buffer的方法有2種:

1.從一個(gè)channel中寫(xiě)入buffer。

2.調(diào)用buffer的put()方法來(lái)自行寫(xiě)入數(shù)據(jù)。

例:

int bytesRead = inChannel.read(buf); //從channel讀入buffer

buf.put(127); //自行寫(xiě)入buffer

put方法有很多的重載形式。以供你用各種不同的方法寫(xiě)入buffer中,比如從一個(gè)特定的position,或者寫(xiě)入一個(gè)array,詳見(jiàn)JavaDoc。

flip()

flip方法將寫(xiě)模式切換成讀模式,調(diào)用flip()方法會(huì)將limit設(shè)置為position,將position設(shè)置回0。

換句話(huà)說(shuō),position標(biāo)志著寫(xiě)模式中寫(xiě)到哪里,切換成讀模式之后,limit標(biāo)志著之前寫(xiě)到哪里,也就是現(xiàn)在能讀到哪里。

從buffer中讀取數(shù)據(jù)

有2種方法可以從buffer中讀取數(shù)據(jù)。

1.從buffer中讀取數(shù)據(jù)到channel中。

2.使用buffer的get()方法自行從buffer中讀出數(shù)據(jù)。

例子:

//從buffer中讀取數(shù)據(jù)到channel中
int bytesWritten = inChannel.write(buf);

//使用buffer的get()方法自行從buffer中讀出數(shù)據(jù)
byte aByte = buf.get();    

get方法有很多的重載形式。以供你用各種不同的方法讀取buffer中的數(shù)據(jù)。例如從特定位置讀取數(shù)據(jù),或者讀一個(gè)數(shù)組出來(lái)。詳見(jiàn)JavaDoc。

rewind()

rewind()方法將position設(shè)置為0,但是不會(huì)動(dòng)buffer里的數(shù)據(jù),這樣可以從頭開(kāi)始重新讀取數(shù)據(jù),limit的值不會(huì)變,這意味著limit依舊標(biāo)志著能讀多少數(shù)據(jù)。

clear()和compact()

當(dāng)你讀完所有的數(shù)據(jù)想要重新寫(xiě)入數(shù)據(jù)時(shí),你可以調(diào)用clear或者compact方法。

當(dāng)你調(diào)用clear()方法的時(shí)候,position被設(shè)置為0,limit被設(shè)置為capacity,換句話(huà)說(shuō),buffer的數(shù)據(jù)雖然都還在,但是buffer被初始化了,處于可以被重寫(xiě)的狀態(tài)。

這也就意味著如果buffer中還有沒(méi)被讀取的數(shù)據(jù),在執(zhí)行clear之后,你無(wú)法知道數(shù)據(jù)讀到哪兒了,剩下的數(shù)據(jù)還有多少。

如果還有沒(méi)有讀完的數(shù)據(jù),但是你想先寫(xiě)數(shù)據(jù),可以用compact()方法,這樣未讀數(shù)據(jù)會(huì)放在buffer前端,可以在未讀數(shù)據(jù)之后跟著寫(xiě)新的數(shù)據(jù)。compact()會(huì)復(fù)制未讀數(shù)據(jù)到buffer前端,然后設(shè)置position為未讀數(shù)據(jù)單位后面緊跟的位置。limit還是設(shè)置為capacity,這和clear是一樣的。現(xiàn)在buffer處于可以寫(xiě)的狀態(tài),但是不會(huì)覆蓋之前未讀完的數(shù)據(jù)。

mark()和reset()

你可以通過(guò)調(diào)用buffer.mark()來(lái)mark一個(gè)buffer中給定的位置。然后你就可以用buffer.reset()方法來(lái)講position設(shè)置回之前mark的位置。

例子:

buffer.mark();

//調(diào)用buffer.get()方法若干次,e.g. 比如在做parsing的時(shí)候

buffer.reset();  //set position back to mark.   
equals() 和 compareTo()

使用這2種方法能夠比較2個(gè)buffer。

equals()

equals()方法用于判斷2個(gè)buffer是否相等,2個(gè)buffer是equal的,當(dāng)它們:

是同一種數(shù)據(jù)類(lèi)型的buffer。

buffer中未讀取的bytes,chars等數(shù)據(jù)個(gè)數(shù)是一樣的,即(limit-position)相等,capacity不需要相等,剩余數(shù)據(jù)的索引也不需要相等。

未讀取的bytes,chars等內(nèi)容是一模一樣的,即各自[position,limit-1]索引的數(shù)據(jù)要完全相等。

如你所見(jiàn),equals()方法只比較buffer的部分內(nèi)容,而不是buffer中所有的數(shù)據(jù),事實(shí)上,它只比較buffer中剩余的元素是否一樣。

compareTo()

compareTo()方法比較兩個(gè)buffer的剩余元素(字節(jié),字符等),用于例如: 排序。

在下列情況下,緩沖區(qū)被認(rèn)為比另一個(gè)緩沖區(qū)“小”:

比較是針對(duì)每個(gè)緩沖區(qū)你剩余數(shù)據(jù)(從 position 到 limit)進(jìn)行的,與它們?cè)?equals() 中的方式相同,直到不相等的元素被發(fā)現(xiàn)或者到達(dá)緩沖區(qū)的上界。如果一個(gè)緩沖區(qū)在不相等元素發(fā)現(xiàn)前已經(jīng)被耗盡,較短的緩沖區(qū)被認(rèn)為是小于較長(zhǎng)的緩沖區(qū)。

if (buffer1.compareTo(buffer2) < 0) { 
// do sth, it means buffer2 < buffer1,not buffer1 < buffer2
    doSth(); 
} 




文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/76360.html

相關(guān)文章

  • JDK10都發(fā)布了,nio你了解多少?

    摘要:而我們現(xiàn)在都已經(jīng)發(fā)布了,的都不知道,這有點(diǎn)說(shuō)不過(guò)去了。而對(duì)一個(gè)的讀寫(xiě)也會(huì)有響應(yīng)的描述符,稱(chēng)為文件描述符,描述符就是一個(gè)數(shù)字,指向內(nèi)核中的一個(gè)結(jié)構(gòu)體文件路徑,數(shù)據(jù)區(qū)等一些屬性。 前言 只有光頭才能變強(qiáng) 回顧前面: 給女朋友講解什么是代理模式 包裝模式就是這么簡(jiǎn)單啦 本來(lái)我預(yù)想是先來(lái)回顧一下傳統(tǒng)的IO模式的,將傳統(tǒng)的IO模式的相關(guān)類(lèi)理清楚(因?yàn)镮O的類(lèi)很多)。 但是,發(fā)現(xiàn)在整理的過(guò)程已...

    YFan 評(píng)論0 收藏0
  • NIO網(wǎng)絡(luò)相關(guān)基礎(chǔ)知識(shí)

    摘要:操作系統(tǒng)是能夠獲取到事件操作完成的事件,基于回調(diào)函數(shù)機(jī)制和操作系統(tǒng)的操作控制實(shí)現(xiàn)事件檢測(cè)機(jī)制。 前面的文章NIO基礎(chǔ)知識(shí)介紹了Java NIO的一些基本的類(lèi)及功能說(shuō)明,Java NIO是用來(lái)替換java 傳統(tǒng)IO的,NIO的一些新的特性在網(wǎng)絡(luò)交互方面會(huì)更加的明顯。 Java 傳統(tǒng)IO的弊端 ????基于JVM來(lái)實(shí)現(xiàn)每個(gè)通道的輪詢(xún)檢查通道狀態(tài)的方法是可行的,但仍然是有問(wèn)題的,檢查每個(gè)通道...

    1fe1se 評(píng)論0 收藏0
  • Netty序章之BIO NIO AIO演變

    摘要:后改良為用線程池的方式代替新增線程,被稱(chēng)為偽異步。最大的問(wèn)題是阻塞,同步。每次請(qǐng)求都由程序執(zhí)行并返回,這是同步的缺陷。這些都會(huì)被注冊(cè)在多路復(fù)用器上。多路復(fù)用器提供選擇已經(jīng)就緒狀態(tài)任務(wù)的能力。并沒(méi)有采用的多路復(fù)用器,而是使用異步通道的概念。 Netty是一個(gè)提供異步事件驅(qū)動(dòng)的網(wǎng)絡(luò)應(yīng)用框架,用以快速開(kāi)發(fā)高性能、高可靠的網(wǎng)絡(luò)服務(wù)器和客戶(hù)端程序。Netty簡(jiǎn)化了網(wǎng)絡(luò)程序的開(kāi)發(fā),是很多框架和公司...

    VincentFF 評(píng)論0 收藏0
  • Netty序章之BIO NIO AIO演變

    摘要:后改良為用線程池的方式代替新增線程,被稱(chēng)為偽異步。最大的問(wèn)題是阻塞,同步。每次請(qǐng)求都由程序執(zhí)行并返回,這是同步的缺陷。這些都會(huì)被注冊(cè)在多路復(fù)用器上。多路復(fù)用器提供選擇已經(jīng)就緒狀態(tài)任務(wù)的能力。并沒(méi)有采用的多路復(fù)用器,而是使用異步通道的概念。 Netty是一個(gè)提供異步事件驅(qū)動(dòng)的網(wǎng)絡(luò)應(yīng)用框架,用以快速開(kāi)發(fā)高性能、高可靠的網(wǎng)絡(luò)服務(wù)器和客戶(hù)端程序。Netty簡(jiǎn)化了網(wǎng)絡(luò)程序的開(kāi)發(fā),是很多框架和公司...

    CntChen 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<