Java nio

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:
    繼承了WritableByteChannelReadableByteChannel.沒有定義新的方法.

  • 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, DoubleBufferByteBuffer類似.

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表示有

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末主慰,一起剝皮案震驚了整個濱河市嚣州,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌共螺,老刑警劉巖该肴,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異藐不,居然都是意外死亡匀哄,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進(jìn)店門雏蛮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來涎嚼,“玉大人,你說我怎么就攤上這事挑秉》ㄌ荩” “怎么了?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵衷模,是天一觀的道長鹊汛。 經(jīng)常有香客問我,道長阱冶,這世上最難降的妖魔是什么刁憋? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮木蹬,結(jié)果婚禮上至耻,老公的妹妹穿的比我還像新娘。我一直安慰自己镊叁,他們只是感情好尘颓,可當(dāng)我...
    茶點故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著晦譬,像睡著了一般疤苹。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上敛腌,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天卧土,我揣著相機與錄音,去河邊找鬼像樊。 笑死尤莺,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的生棍。 我是一名探鬼主播颤霎,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了友酱?” 一聲冷哼從身側(cè)響起晴音,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎粹污,沒想到半個月后段多,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡壮吩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年进苍,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鸭叙。...
    茶點故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡觉啊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出沈贝,到底是詐尸還是另有隱情杠人,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布宋下,位于F島的核電站嗡善,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏学歧。R本人自食惡果不足惜罩引,卻給世界環(huán)境...
    茶點故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望枝笨。 院中可真熱鬧袁铐,春花似錦、人聲如沸横浑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽徙融。三九已至洒缀,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間欺冀,已是汗流浹背树绩。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留脚猾,地道東北人葱峡。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓砚哗,卻偏偏與公主長得像龙助,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,781評論 2 354

推薦閱讀更多精彩內(nèi)容