java的NIO
包含通道Channel,緩沖區Buffer,選擇器selector三個重要的類,
IO多路復用
指的是一個行程/執行緒可以同時監視多個檔案描述符(一個網路連接,作業系統底層使用一個檔案描述符來表示),一旦其中的一個或者多個檔案描述符可讀或者可寫,系統內核就通知該行程/執行緒,
緩沖區Buffer
Buffer是抽象類,Buffer類是一個非執行緒安全類, 主要資料型別有 ByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer、ShortBuffer、MappedByteBuffer(用于記憶體映射),
capacity屬性指容量,寫入的資料物件的數量一旦初始化,就不能再改;
position屬性表示當前位置,讀寫模式變化時,position會進行調整;limit屬性表示讀寫的最大上限,讀寫模式切換時變化,
屬性mark(標記)就是相當一個暫存屬性,暫時保存position的值,方便后面的重復使用position值,
allocate()創建緩沖區, put()寫入到緩沖區,flip()翻轉(將寫入模式翻轉成讀取模式),get()從緩沖區讀取,rewind() 倒帶(重新讀取,positon=0,mark清除),
Buffer.mark()方法的作用是將當前position的值保存起來,放在mark屬性中,讓mark屬性記住這個臨時位置;
之后,可以呼叫Buffer.reset()方法將mark的值恢復到position中,clear( )清慷訓沖區,

通道Channel
通道可以表示一個底層的檔案描述符,例如硬體設備、檔案、網路連接等,FileChannel(阻塞,檔案IO讀寫)、SocketChannel(TCP連接讀寫)、ServerSocketChannel(服務器監聽TCP連接的通道)、DatagramChannel(UDP協議資料讀寫),
獲取File通道
輸入輸出流 -> getChannel() -> FileChannel,讀取:int read(ByteBuffer buf)(寫入緩沖區),(緩沖區翻轉 flip)寫入通道:int write(ByteBuffer buf)(讀取緩沖區),關閉通道,close(),刷盤:channel.force(true)方法,強制重繪到磁盤,
高效檔案復制transferFrom方法,不可以被選擇器選擇,沒有非阻塞模式,
SocketChannel傳輸通道
靜態方法 open() 獲得 SocketChannel -> 設定為非阻塞模式 -> connect(ip,port)發起連接,判斷 finishConnect() ? 是否完成連接,TCP
ServerSocketChannel通道
監聽套接字的 accept()方法,來獲取新連接的套接字通道:server.accept()->SocketChannel->設定非阻塞模式,read,flip,write, shutdownOutput()發送-1 終止標記,close,用Selector通道選擇器判斷通道何時可讀,TCP
DatagramChannel資料報通道
open靜態方法得 channel->channel.configureBlocking(false)方法,設定成非阻塞模式->接收資料,呼叫bind方法系結資料報的監聽埠channel.socket().bind() -->
讀取 receive(ByteBuffer buf)-> flip() 切換讀取buf -> send(buf,new Obj(ip,port))->clear切換寫入buf->close關閉,UDP
Selector選擇器
選擇器的使命是完成IO的多路復用,一個通道代表一條連接通路,通過選擇器可以同時監控多個通道的IO(輸入輸出)狀況,選擇器和通道的關系,是監控和被監控的關系,
Channel.register(Selector sel, int ops)方法將通道實體注冊到一個選擇器中,
監聽事件
可讀:SelectionKey.OP_READ,可寫:SelectionKey.OP_WRITE,連接就緒(完成握手連接): SelectionKey.OP_CONNECT,接收就緒(新連接到來):SelectionKey.OP_ACCEPT
SelectableChannel可選擇通道
FileChannel檔案通道就不能被選擇器復用,前提:判斷它是否繼承了抽象類SelectableChannel(可選擇通道).,
SelectionKey選擇鍵
一旦在通道中發生了某些IO事件(就緒狀態達成),并且是在選擇器中注冊過的IO事件,就會被選擇器選中,并放入SelectionKey選擇鍵的集合中,簡單地理解為:選擇鍵,就是被選中了的IO事件,
選擇器使用流程
Selector.open() 靜態工廠方法 -> 實體channel.register(Selector sel, int ops)(channel必須設定非阻塞模式)
注意:一個通道,并不一定要支持所有的四種IO事件 -> 選出感興趣的IO就緒事件, selector.select()-> 選出已經注冊的、已經就緒的IO事件,
保存到SelectionKey選擇鍵集合中 -> selector.selectedKeys() ->Set<SelectionKey -> iterator: SelectionKey ->IO事件對應業務處理->最后 iterator.remove當前key,
查詢多載方法
select(): 阻塞呼叫, select(long timeout) 阻塞或指定時長,selectNow():非阻塞,不管有沒有IO事件,都會立刻回傳;
select() 方法回傳的整數值(int整數型別),表示 2次 查詢之間發生了IO事件的通道數量,
讀書筆記
閱讀: 《Netty、Redis、Zookeeper高并發實戰》
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/119100.html
標籤:Java
