1. java nio
java nio 意為java new IO. 它與java IO有以下三點區(qū)別:
- nio是面向
緩存
的, 而io是面向流
的. - nio是
非阻塞
的, 而io是完全阻塞
的. - 在nio中, 一個
Selector
可以管理多個通道, 而io則無此能力.
2. nio的三個關(guān)鍵組件?
- Channel: 通道, 即數(shù)據(jù)源.
- Buffer: 緩沖區(qū)
- Selector: 選擇器, 一個
Selector
可以管理多個Channel
.
數(shù)據(jù)可以從Channel
讀入Buffer
, 也可以從Buffer
寫入Channel
.
3. Channel
Channel定義了以下幾個接口:
-
Channel
: 所有Channel
的基類.
boolean isOpen();
-
ReadableByteChannel
: 定義了將數(shù)據(jù)從Channel讀入Buffer的操作,
// 返回讀取的字節(jié)數(shù), 讀完則返回`-1`.
int read(Buffer b);
-
WritableByteChannel
: 定義了將數(shù)據(jù)從Buffer寫入Channel的操作.
// 返回寫入的字節(jié)數(shù),可能為零
int write(Buffer b);
注:只會寫入未讀過的數(shù)據(jù).
-
GatheringByteChannel
: 將多個Buffer中的數(shù)據(jù)依次寫入Channel.
// 返回寫入的字節(jié)數(shù),可能為零
long write(Buffer[] fs);
long write(Buffer[] fs, int offset, int length);
注:只會寫入未讀過的數(shù)據(jù).
-
ScatteringByteChannel
: 將Channel中的數(shù)據(jù)依次讀入多個Buffer中
long read(Buffer[] bs);
long read(Buffer[] bs, int offset, int length);
ByteChannel
:
繼承了WritableByteChannel
和ReadableByteChannel
.沒有定義新的方法.InterruptibleChannel
: 通道的異步關(guān)閉
void close();
3.1 FileChannel
操作文件
可以通過FileInputStream
, FileOutputStream
, RandomAccessFile
對象的getChannel()
方法獲取.
// 通道中文件的位置, 返回從文件開始到當(dāng)前位置的字節(jié)數(shù)
long position();
// 設(shè)置文件的位置
FileChannel position(long newPosition);
// 文件大小(字節(jié))
long size();
// 將文件截取為指定大小, 返回截取后的文件大小(字節(jié))
FileChannel truncate(long size);
// 將通道中文件的更新寫入磁盤
void force(boolean metaData);
// 將此通道的文件寫入到給定的可寫入通道, 返回實際寫入的字節(jié)數(shù)
long transferTo(long position, long count, WritableByteChannel channel);
// 從給定的通道讀入數(shù)據(jù), 返回實際讀取的字節(jié)數(shù)
long transferFrom(ReadableByteChannel src, long position, long count);
// 將此通道的文件區(qū)域直接映射到內(nèi)存中。
MappedByteBuffer map(FileChannel.MapMode mode, long position, long size);
// 獲取鎖, 會阻塞
FileLock lock();
// 獲取鎖, 會阻塞
FileLock lock(long position, long size, boolean shared);
// 獲取鎖, 不會阻塞
FileLock trylock();
// 獲取鎖, 不會阻塞
FileLock trylock(long position, long size, boolean shared);
3.2 DatagramChannel
處理UDP包的通道.
// 連接通道的套接字
DatagramChannel connect(SocketAddress remote);
// 斷開連接
DatagramChannel disConnect();
// 是否連接
boolean isConnected();
// 打開通道
DatagramChannel open();
// 接收數(shù)據(jù)
SocketAddress receive(ByteBuffer dst);
// 發(fā)送數(shù)據(jù)
int send(ByteBuffer src, SocketAddress target);
// 獲取此通道的套接字
DatagramSocket socket();
// 返回此通道所支持的操作
int validOps();
3.3 SocketChannel
處理TCP包數(shù)據(jù)
// 連接
boolean connect(SocketAddress remote);
// 是否完成連接
boolean finishConnect();
// 是否已連接
boolean isConnected();
// 是否正在進(jìn)行連接操作
boolean isConnectionPending();
// 打開通道
SocketChannel open();
// 打開通道并連接到遠(yuǎn)程地址
SocketChannel open(SocketAddress remote);
// 獲取套接字
Socket socket();
// 返回通道所支持的操作
int validOps();
3.4 ServerSocketChannel
監(jiān)聽套接字
// 接收連接并生成一個新的SocketChannel
SocketChannel accept();
// 打開通道
ServerSocketChannel open();
// 獲取通道的服務(wù)器套接字
ServerSocket socket();
// 返回通道所支持的操作
int validOps();
3.5 SelectableChannel
// 設(shè)置通道的阻塞模式, 在將其注冊到Selector時必須要設(shè)置其為false.
SelectableChannel configureBlocking(boolean block);
// 將通道注冊到Selector
SelectionKey register(Selector sel, int ops, Object att);
注:DatagramChannel, SocketChannel, ServerSocketChannel
實現(xiàn)了該接口, FileChannel
未實現(xiàn)該接口, 故FileChannel
不能注冊到Selector
.
4. Buffer
緩沖區(qū), 除了boolean以外所有的基本類型都一個與之對應(yīng)的Buffer.
// Buffer的容量
int capacity();
// 清除Buffer, 并未清除緩沖區(qū)的實際內(nèi)容, 只是將其當(dāng)前位置置0, 限制設(shè)置為容量, 丟棄了標(biāo)記.
Buffer clear();
// 首先將限制設(shè)置為當(dāng)前位置兼吓,然后將位置設(shè)置為 0丈积。如果已定義了標(biāo)記,則丟棄該標(biāo)記。
// 在read和put操作之后, 調(diào)用此方法后就可以write或get了.
Buffer flip();
// 是否有剩余
boolean hasRemaining();
// 是否是直接緩沖區(qū)
boolean isDirect();
// 是否只讀
boolean isReadOnly();
// Buffer的限制
int limit();
// 設(shè)置Buffer的限制
Buffer limit(int newLimit);
// 在當(dāng)前位置設(shè)置標(biāo)記
Buffer mark();
// 當(dāng)前位置
int position();
// 設(shè)置新的位置
Buffer position(int newPosition);
// 返回剩余
int remaining();
// 將當(dāng)前位置更改為上次mark()的位置
Buffer reset();
// 可以從頭開始重新讀取Buffer中的數(shù)據(jù)
Buffer rewind();
4.1 ByteBuffer
字節(jié)緩沖區(qū)
// 分配給定容量的緩沖區(qū)
ByteBuffer allocate(int capacity);
ByteBuffer allocateDirect(int capacity);
// 壓縮緩沖區(qū), 刪除已讀數(shù)據(jù), 未讀數(shù)據(jù)前移, 然后接著往后寫入.
ByteBuffer compact();
// 創(chuàng)建共享此緩沖區(qū)內(nèi)容的新的字節(jié)緩沖區(qū)。
ByteBuffer duplicate();
// 創(chuàng)建共享此緩沖區(qū)內(nèi)容的新的字節(jié)緩沖區(qū)
ByteBuffer slice();
// 創(chuàng)建此字節(jié)緩沖區(qū)的視圖亭珍,作為 char 緩沖區(qū)。
// short, int, long, float, double都有與之對應(yīng)的asXxxBuffer()
CharBuffer asCharBuffer();
// 緩沖區(qū)當(dāng)前(或指定)位置的字節(jié)
byte get();
byte get(int index);
// 將此緩沖區(qū)的字節(jié)傳輸?shù)浇o定的目標(biāo)數(shù)組中
ByteBuffer get(byte[] dst);
// 讀取此緩沖區(qū)的當(dāng)前位置之后的兩個字節(jié)枝哄,并將它們組成 char 值肄梨,然后將該位置增加 2。
// short, int, long, float, double都有與之對應(yīng)的getXxx()方法
char getChar();
char getChar(int index);
// 將給定的字節(jié)寫入緩沖區(qū)
ByteBuffer put(byte b);
ByteBuffer put(int index, byte b);
ByteBuffer put(byte[] src);
ByteBuffer put(ByteBuffer src);
// 將指定 char 值的字節(jié)按順序?qū)懭氲酱司彌_區(qū)的當(dāng)前位置膘格,然后將該位置增加 2。
// short, int, long, float, double都有與之對應(yīng)的putXxx()方法
ByteBuffer putChar(char value);
ByteBuffer putChar(int index, char value);
// 將 byte 數(shù)組包裝到緩沖區(qū)中财松。緩沖區(qū)修改將導(dǎo)致數(shù)組修改瘪贱,反之亦然。
ByteBuffer wrap(byte[] array);
ShortBuffer
, CharBuffer
, IntBuffer
, LongBuffer
, FloatBuffer
, DoubleBuffer
與ByteBuffer
類似.
5. Selector
一個Selector可以處理多個通道.
// 關(guān)閉選擇器
void close();
boolean isOpen();
// 返回此選擇器的鍵集辆毡。
Set<SelectionKey> keys();
Set<SelectionKey> selectKeys();
// 打開一個選擇器
Selector open();
// 返回創(chuàng)建此通道的提供者菜秦。
SelectorProvider provider();
// 選擇一組鍵,其相應(yīng)的通道已為 I/O 操作準(zhǔn)備就緒舶掖。會阻塞. 沒有返回0
int select();
int select(long timeout);
// 選擇一組鍵球昨,其相應(yīng)的通道已為 I/O 操作準(zhǔn)備就緒。不會阻塞
int selectNow();
// 使尚未返回的第一個選擇操作立即返回眨攘。
Selector wakeup();
6. SelectionKey
選擇器Selector與Channel的對應(yīng)關(guān)系.
常量:
- OP_ACCEPT:
- OP_CONNECT:
- OP_READ:
- OP_WRITE:
方法:
// 設(shè)置附加對象
Object attach(Object obj)
// 獲取附加對象
Object attach();
// 取消此key表示的Channel與Selector之間的注冊關(guān)系
void cancel();
// 獲取Channel
SelectableChannel channel();
// 獲取注冊的操作集
int interestOps();
// 設(shè)置操作集
SelectionKey interestOps(int ops);
// 是否可接受新的連接
boolean isAcceptable();
// 是否已連接
boolean isConnectable();
// 是否可讀
boolean isReadable();
// 是否可寫
boolean isWritable();
// 是否有效
boolean isValid();
// 已就緒的操作集
readyOps();
// 獲取Selector
Selector selector();
關(guān)于操作集位運算:
| : 表示相加.
&~: 表示有則取消
&: 結(jié)果為0表示沒有, 大于0表示有