NIO包含下面幾個核心的組件:
- Channels
- Buffer
- Selector
整個NIO體系包含的類遠遠不止這幾個,但是在筆者看來Channels,Buffer和Selector組成了這個核心的API。其他的一些組件,比如Pipe和FileLock僅僅只作為上述三個的負責類。因此在概覽這一節中,會重點關注這三個概念。其他的組件會在各自的部分單獨介紹。
通道和緩沖區(Channels and Buffers)
通常來說NIO中的所有IO都是從Channel開始的。Channel和流有點類似。通過Channel,我們即可以從Channel把數據寫到Buffer中,也可以把數據沖Buffer寫入到Channel,下圖是一個示意圖:
Java NIO: Channels read data into Buffers, and Buffers write data into Channels
有很多的Channel,Buffer類型。下面列舉了主要的幾種:
- FileChannel
- DatagramChannel
- SocketChannel
- ServerSocketChannel
正如你看到的,這些channel基於於UDP和TCP的網絡IO,以及文件IO。 和這些類一起的還有其他一些比較有趣的接口,在本節中暫時不多介紹。為了簡潔起見,我們會在必要的時候引入這些概念。 下面是核心的Buffer實現類的列表:
- ByteBuffer
- CharBuffer
- DoubleBuffer
- FloatBuffer
- IntBuffer
- LongBuffer
- ShortBuffer
這些Buffer涵蓋了可以通過IO操作的基礎類型:byte,short,int,long,float,double以及characters. NIO實際上還包含一種MappedBytesBuffer,一般用於和內存映射的文件。
選擇器(Selectors)
選擇器允許單線程操作多個通道。如果你的程序中有大量的鏈接,同時每個鏈接的IO帶寬不高的話,這個特性將會非常有幫助。比如聊天服務器。 下面是一個單線程中Slector維護3個Channel的示意圖:
Java NIO: A Thread uses a Selector to handle 3 Channel's
要使用Selector的話,我們必須把Channel注冊到Selector上,然后就可以調用Selector的select()方法。這個方法會進入阻塞,直到有一個channel的狀態符合條件。當方法返回后,線程可以處理這些事件。