NIO的寫操作分析

2021-08-28 01:44:45 字數 1603 閱讀 3732

很多人對nio的寫操作理解的不深,不知道為什麼要註冊寫事件,何時註冊寫事件,為什麼寫完之後要取消註冊寫事件。

selector.iswriteable()方法監控的是核心的寫緩衝器是否可寫,所以除非核心的寫緩衝區滿了,否則一旦乙個socketchannel註冊了寫事件,每次selector都會選中這個socketchannel,進入到iswriteable()分支中去。

實際上伺服器端寫訊息時完全可以不註冊寫事件,直接呼叫socketchannel.write(bytebuffer),也能把資料寫到緩衝區並傳送出去。但是這種情況下selector不會選擇到iswriteable()分支。在寫緩衝區滿的情況下處理也不靈活,需要while(bytebuffer.hasremain())來檢查寫的狀態,會導致cpu空轉while.

更好的做法是註冊寫事件。註冊寫事件也有兩種做法,一種是socketchannel.register(selector, selectionkey.op_write),直接註冊到socketchannel。第二種是用selectionkey.interestops(selectionkey.interestops() | selectionkey.op_write),用selectionkey來註冊。每個selectionkey只會關聯乙個socketchannel,相當於註冊到了socketchannel上。

所以nio寫方法的一般做法是:

1. 註冊寫事件

2. 寫資料

3. 取消註冊寫事件

注意第3步,每次寫完之後要取消註冊寫事件,selectionkey.interestops(selectionkey.interestops() & ~selectionkey.op_write),否則只要核心寫緩衝區可寫,這個socketchannel就會一直被selector選中。

由於有兩種註冊寫事件的方式,所以導致寫資料也有兩種做法,如果用socketchannel來註冊寫事件,那麼直接用socketchannel來寫bytebuffer。

更好的一種做法是第二種,將業務處理和底層socket操作隔離,採用selectionkey的attachment,把業務資料用attachment的方式和socketchannel繫結

。在socketchannel註冊事件時可以新增attachment,比如socketchannel.register(selector, selectionkey.op_read, bytebuffer.allocate(1024));

業務方法只需要操作attachment,往attachment裡面寫,然後在selector.iswriteable()分支裡面取出寫好的attachment,然後呼叫socketchannel.write(bytebuffer) 方法來把資料寫到channel。

大部分的框架都採用第二種方式,比如thrift的tnonblockingserver處理寫事件時,採用乙個業務類framebuffer來封裝業務資料的讀寫,把framebuffer作為attachment繫結到socketchannel,並用framebuffer記錄讀寫的狀態。這樣業務功能只需要處理framebuffer,

tnonblockingserver來處理socketchannel實際的寫操作。

檔案操作 NIO

在我們之前介紹了檔案操作都是通過bio進行實現的,這裡我們以nio來實現檔案的讀寫,nio建立的目的就是實現高速的i o,提高其效率,nio與bio最重要的區別就是資料打包和傳輸方式,原來的i o以流的方式處理資料,而nio以塊的方式處理資料。面向流的i o系統一次乙個位元組地處理資料,乙個輸入流產...

SRAM儲存器寫操作分析

目前針對不同的應用市場,sram產品的技術發展已經呈現出了兩大趨勢 一是向高效能通訊網路所需的高速器件發展,由於讀寫速度快,sram儲存器被用作計算機中的快取記憶體,提高它的讀寫速度對於充分發揮微處理器的優勢,改善處理器效能有著積極的意義。另乙個是降低功耗,以適應蓬勃發展的可攜式應用市場。英尚微介紹...

NIO字符集操作

示例程式 在開啟相應的檔案 將輸入資料讀入名為 inputdata 的 bytebuffer 之後,我們的程式必須建立 iso 8859 1 latin1 字符集的乙個例項 charset latin1 charset.forname iso 8859 1 然後,建立乙個解碼器 用於讀取 和乙個編碼...