一、NIO簡介
Java NIO是Java1.4之后推出來的一套IO接口,這里所說的新是相對(duì)于原有標(biāo)準(zhǔn)的Java IO和Java Networking接口。NIO提供了一種完全不同的操作方式。
NIO中的N可以理解為Non-blocking,不單純是new。
它是面向緩沖的,基于通道的I/O操作方法。隨著JDK7的推出,NIO系統(tǒng)得到了擴(kuò)展,為文件系統(tǒng)功能和文件處理提供了增強(qiáng)的支持。由于NIO文件類支持的這些新的功能,NIO被廣泛應(yīng)用于文件處理。
二、NIO的特性/NIO與IO區(qū)別
1.Channels and Buffers(通道和緩沖區(qū))
IO是面向流的,NIO是面向緩沖區(qū)的
(1)標(biāo)準(zhǔn)的IO編程接口是面向字節(jié)流和字符流的。而NIO是面向通道和緩沖區(qū)的,數(shù)據(jù)總是從通道中讀到buffer緩沖區(qū)內(nèi),或者從buffer緩沖區(qū)寫入到通道中;( NIO中的所有I/O操作都是通過一個(gè)通道開始的。)
(2)Java IO面向流意味著每次從流中讀一個(gè)或多個(gè)字節(jié),直至讀取所有字節(jié),它們沒有被緩存在任何地方;
(3)Java NIO是面向緩存的I/O方法。 將數(shù)據(jù)讀入緩沖器,使用通道進(jìn)一步處理數(shù)據(jù)。 在NIO中,使用通道和緩沖區(qū)來處理I/O操作。
2.Non-blocking IO(非阻塞IO)
IO流是阻塞的,NIO流是不阻塞的。
(1)Java NIO使我們可以進(jìn)行非阻塞IO操作。比如說,單線程中從通道讀取數(shù)據(jù)到buffer,同時(shí)可以繼續(xù)做別的事情,當(dāng)數(shù)據(jù)讀取到buffer中后,線程再繼續(xù)處理數(shù)據(jù)。寫數(shù)據(jù)也是一樣的。另外,非阻塞寫也是如此。一個(gè)線程請(qǐng)求寫入一些數(shù)據(jù)到某通道,但不需要等待它完全寫入,這個(gè)線程同時(shí)可以去做別的事情。
(2)Java IO的各種流是阻塞的。這意味著,當(dāng)一個(gè)線程調(diào)用read() 或 write()時(shí),該線程被阻塞,直到有一些數(shù)據(jù)被讀取,或數(shù)據(jù)完全寫入。該線程在此期間不能再干任何事情了。
3.Selectors(選擇器)
NIO有選擇器,而IO沒有。
(1)選擇器用于使用單個(gè)線程處理多個(gè)通道。因此,它需要較少的線程來處理這些通道。
(2)線程之間的切換對(duì)于操作系統(tǒng)來說是昂貴的。 因此,為了提高系統(tǒng)效率選擇器是有用的。
三、讀數(shù)據(jù)和寫數(shù)據(jù)方式
通常來說NIO中的所有的IO都是從Channel(通道)開始的。
(1)從通道進(jìn)行數(shù)據(jù)讀?。簞?chuàng)建一個(gè)緩沖區(qū),然后發(fā)起請(qǐng)求從通道讀取數(shù)據(jù)。
(2)從通道進(jìn)行數(shù)據(jù)寫入:創(chuàng)建一個(gè)緩沖區(qū),填充數(shù)據(jù),并要求往通道寫入數(shù)據(jù)。
四、NIO核心組件簡單介紹
NIO包含三個(gè)核心的組件:Channels、Buffers、Selectors
(1)通道
在Java NIO中,主要使用的通道如下(涵蓋了UDP和TCP網(wǎng)絡(luò)IO、以及文件IO)
1)DatagramChannel 2) SocketChannel 3) FileChannel 4)ServerSocketChannel
(2) 緩沖區(qū)
在Java NIO中使用的核心緩沖區(qū)如下(涵蓋了IO發(fā)送的基本數(shù)據(jù)類型)
1)ByteBuffer 2) CharBuffer 3) ShortBuffer 4) IntBuffer 5) FloatBuffer 6) DoubleBuffer 7) LongBuffer
(3)選擇器
Java NIO提供了“選擇器”的概念。這是一個(gè)可以用于監(jiān)視多個(gè)通道的對(duì)象,如數(shù)據(jù)到達(dá),連接打開等。因此。單線程可以監(jiān)視多個(gè)通道中的數(shù)據(jù)。
如果應(yīng)用程序有多個(gè)通道(連接)打開,但每個(gè)連接的流量都很低,則可以考慮使用它。例如:在聊天服務(wù)器中。
要使用Selector的話,我們必須把Channel注冊(cè)到Selector上,然后就可以調(diào)用Selector的select()方法。這個(gè)方法會(huì)進(jìn)入阻塞,直到有一個(gè)channel的狀態(tài)符合條件。當(dāng)條件返回后,線程可以處理這些事件。