亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Java NIO 基礎(chǔ)(一)

hizengzeng / 1709人閱讀

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

Java NIO 教程 NIO是什么?

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

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

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

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

Java NIO 總覽

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

Channels

Buffers

Selectors

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

Channels和Buffers的關(guān)系

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

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

FileChannel

DatagramChannel

SocketChannel

ServerSocketChannel

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

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

ByteBuffer

CharBuffer

DoubleBuffer

FloatBuffer

IntBuffer

LongBuffer

ShortBuffer

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

selectors

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

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

NIO Channels

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

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

channel可以異步地讀和寫。

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

channel的實現(xiàn)

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

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

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

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

ServerSocketChannel 以一個web服務(wù)器的形式,監(jiān)聽到來的TCP連接,對每個連接建立一個SocketChannel。

一個簡單的channel例子

使用一個FileChannel將數(shù)據(jù)讀入一個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()的意思是讀寫轉(zhuǎn)換,首先你讀入一個buffer,然后你flip,轉(zhuǎn)換讀寫,然后再從buffer中讀出,buffer的操作接下來會講。

NIO buffer

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

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

buffer的基本使用

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

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

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

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

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

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

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

調(diào)用clear()

調(diào)用compact()

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

一個簡單的buffer使用例子:

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

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

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

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

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

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

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

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

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

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

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

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

buffer的種類

Java NIO中有以下這些buffer種類:

ByteBuffer

MappedByteBuffer //比較特殊,會在以后講解

CharBuffer

DoubleBuffer

FloatBuffer

IntBuffer

LongBuffer

ShortBuffer

創(chuàng)建一個buffer

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

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

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

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

寫入buffer的方法有2種:

1.從一個channel中寫入buffer。

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

例:

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

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

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

flip()

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

換句話說,position標(biāo)志著寫模式中寫到哪里,切換成讀模式之后,limit標(biāo)志著之前寫到哪里,也就是現(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ù),或者讀一個數(shù)組出來。詳見JavaDoc。

rewind()

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

clear()和compact()

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

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

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

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

mark()和reset()

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

例子:

buffer.mark();

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

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

使用這2種方法能夠比較2個buffer。

equals()

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

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

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

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

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

compareTo()

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

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

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

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




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

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/76360.html

相關(guān)文章

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

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

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

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

    1fe1se 評論0 收藏0
  • Netty序章之BIO NIO AIO演變

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

    VincentFF 評論0 收藏0
  • Netty序章之BIO NIO AIO演變

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

    CntChen 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<