簡介
channel詳解
異步io和channelfuture
channel的層級結構
釋放資源
事件處理
總結
channel是連接配接bytebuf和event的橋梁,netty中的channel提供了統一的api,通過這種統一的api,netty可以輕松的對接多種傳輸類型,如oio,nio等。今天本文将會介紹channel的使用和channel相關的一些概念。
channel是什麼? channel是一個連接配接網絡輸入和io處理的橋梁。你可以通過channel來判斷目前的狀态,是open還是connected,還可以判斷目前channel支援的io操作,還可以使用channelpipeline對channel中的消息進行處理。
先看下channel的定義:
可以看到channel是一個接口,它繼承了attributemap, channeloutboundinvoker, comparable三個類。comparable表示這個類可以用來做比較。attributemap用來存儲channel的各種屬性。channeloutboundinvoker主要負責channel和外部 socketaddress 進行連接配接和對寫。
再看下channel中定義的方法:
可以看出channel中定義的方法是多種多樣的,這些方法都有些什麼特點呢?接下來一一為您講解。
netty中所有的io都是異步io,也就是說所有的io都是立即傳回的,傳回的時候,io可能還沒有結束,是以需要傳回一個channelfuture,當io有結果之後,會去通知channelfuture,這樣就可以取出結果了。
channelfuture是java.util.concurrent.future的子類,它除了可以拿到線程的執行結果之外,還對其進行了擴充,加入了目前任務狀态判斷、等待任務執行和添加listener的功能。
其他的功能都很好了解,它的突破在于可以對channelfuture添加listener,我們列出一個添加listener的方法:
添加的listener會在future執行結束之後,被通知。不需要自己再去調用get等待future結束。這裡實際上就是異步io概念的實作,不需要主動去調用,當你完成之後來通知我就行。非常的美好!
channelfuture 有兩個狀态:uncompleted或者completed,分别代表任務的執行狀态。
當一個io剛開始的時候,傳回一個channelfuture對象,這個對象的初始狀态是uncompleted。注意,這個狀态下的io是還未開始工作的狀态。當io完成之後,不管是succeeded, failed 或者 cancelled狀态,channelfuture的狀态都會轉換成為completed。
下圖展示的是channelfuture狀态和io狀态的對應圖:
如果要監控io的狀态,可以使用上面我們提到的 addlistener 方法,為channelfuture添加一個channelfuturelistener。
如果要等待io執行完畢,還有一個await()方法,但是這個方法會去等待io執行完畢,是一個同步的方法,是以并不推薦。
相比而言,addlistener(genericfuturelistener)是一個非阻塞的異步方法,将會把一個channelfuturelistener添加到channelfuture中,當io結束之後會自動通知channelfuturelistener,非常好用。
對于處理io操作的channelhandler來說,為了避免io的阻塞,一定不要在channelhandler的io方法中調用await(),這樣有可能會導緻channelhandler因為io阻塞導緻性能下降。
下面舉兩個例子,一個是錯誤的操作,一個是正确的操作:
大家可以對比下上面兩種寫法的差別。
另外要注意的是channelfuture中的這些await方法比如:await(long), await(long, timeunit), awaituninterruptibly(long), 或者 awaituninterruptibly(long, timeunit)可以帶一個過期時間,大家要注意的是這個過期時間是等待io執行的時間,并不是io的timeout時間,也就是說當await逾時之後,io還有可能沒有執行完成,這就導緻了下面的代碼有可能報錯:
上面的代碼可以改成下面的例子:
netty中的channel是有層級結構的,通過parent屬性可擷取這種層級結構。parent擷取的對象和channel的建立方式有關。比如如果是一個被serversocketchannel accepted的socketchannel,那麼它的parent就是serversocketchannel。
和所有的io一樣,channel在用完之後也需要被釋放,需要調用close()或者close(channelpromise) 方法。
channel負責建立連接配接,建立好的連接配接就可以用來處理事件channelevent了,實際上channelevent是由定義的一個個channelhandler來處理的。而channelpipeline就是連接配接channel和channelhandler的橋梁。
我們将會下下一章詳細講解channelevent、channelhandler和channelpipeline的關聯關系,敬請期待。
channel在netty中是做為一個關鍵的通道而存在的,後面的event和handler是以channel為基礎運作的,是以說channel就是netty的基礎,好了,今天的介紹到這裡就結束了,敬請期待後續的文章。
本文已收錄于 http://www.flydean.com/04-netty-channel/ 最通俗的解讀,最深刻的幹貨,最簡潔的教程,衆多你不知道的小技巧等你來發現! 歡迎關注我的公衆号:「程式那些事」,懂技術,更懂你!