NIO學習一、NIO簡介

大多多發表於2017-12-03

最近在學習NIO,根據學習總結了一下,如果有不對的地方,請大佬指出。

一、NIO的簡介

NIO,就是new io,從jdk  1.4開始引入的新的api,它跟IO的作用相同。它與傳統的IO相比,有如下特性:

1)NIO是面向緩衝區的,IO是面向流的。
2)IO是阻塞的操作,如果一個io的read或者write沒有得到資料的時候,會一直等待,當前執行緒不能做其他
的事情。而NIO提供了非阻塞方式,它可以在沒有資料到來之前,先做其他的事情,資料到來之後進行處理。
3)NIO提供了選擇器selector,通過它允許一個執行緒監視多個通道,避免了申請多個執行緒浪費資源以及執行緒
間的頻繁切換,以此提高了資源的利用率。

二、Java NIO核心部分:

 Channel、Buffer、Selector
 Channel表示通道,通道的一端連線Buffer,另一端連線需要被操作的資源(假設資源是檔案檔案)。它
 相當於一根管子,buffer中的資料可以通過管子寫入被操作的資源當中,也可以將資源通過管子寫入到buffer中去。
      常用的Channel有:
           FileChannel
           DatagramChannel
           SocketChannel
           ServerSocketChannel
       其中FileChannel是阻塞的,其他的可以設定成非阻塞的。
 Buffer:表示緩衝區,本質是一個可以讀寫的記憶體空間,channel中的資料從資源流向buffer或者從buffer
 流向資源,緩衝區有四個重要的欄位,讀取寫入緩衝區的時候,都是操作這幾個欄位實現的:
            capacity:記憶體塊可以讀入的大小。
            position:當前指向的位置,每讀取一個位元組後,它都會向後移動一個位置
 當前position位置
            mark:標定的一個特定的位置,標定好後可以使用reset方法回到這個位置。
         nio中,資源的讀寫操作都是通過buffer實現的。 
      常用的Buffer有:
            ByteBuffer
            MappedByteBuffer
            CharBuffer
            DoubleBuffer
            FloatBuffer
            IntBuffer
            LongBuffer
            ShortBuffer  
 Selector:nio中最重要的一部分,一個selector可以管理多個channel,當selecot管
理的channel沒有準備好的時候,selecot就阻塞,當有channel準備好需要操作的時候,
selecot就被喚醒。傳統的IO方式下,如果有多個請求到來,一般會開闢多個執行緒來處理這些
請求,如果請求的資源沒有準備好,那麼執行緒就會處於阻塞狀態,極大的浪費了資源。而NIO採
用多路複用的技術,當有請求到來的時候,先註冊到selector中,當註冊到selector中感興
趣的請求資源準備好後,才會進行處理,(注意:註冊的channel必須是同步非阻塞的)避免了
傳統IO中開闢的多個執行緒阻塞佔用資源的問題。當你的每個通道的資料傳輸量比較低的時候,使
用它會非常合適。
   ps:Selector中底層設計中涉及IO多路複用,同步非阻塞知識,不懂的話先瞅瞅它們。

三、使用NIO操作的基本例子

    @Test
    public void test1() throws IOException {
        //獲取可以讀寫的一個檔案
        RandomAccessFile randomAccessFile=new RandomAccessFile("C:\\Users\\e550c\\Desktop\\日結.txt","rw");
        //1、獲取通道
        FileChannel channel=randomAccessFile.getChannel();
       //2、將通道中資料送往緩衝區
        ByteBuffer byteBuffer=ByteBuffer.allocate(48);
        //3、將channel中資料資料讀入byteBuffer
        int length=channel.read(byteBuffer);//獲取緩衝區長度
        while(length!=-1){
            byteBuffer.flip();//4、讀完資料後,呼叫它可以將position設定為0,limit設定為當前讀取到的位置
                            //以從而可以讀取在這個區間中的資料
            while(byteBuffer.hasRemaining()){//當讀取的buffer中有資料的時候,它會返回true
                System.out.println((char)byteBuffer.get());//輸出

            }
            byteBuffer.clear();//清空緩衝區
        }
        randomAccessFile.close();
    }

相關文章