經過netty解析future

 netty中的future繼承自jdk中cocurrent包下future的接口。編程

Future的V能夠是void,不必定是有返回值的,因此經過返回值來判斷task isDone()是錯誤的。因此isDone的判斷不該該經過返回值來作。只有isDone了以後,纔去作get操做。因此get裏面也會拋異常。數組

經過isDone來判斷是否結束了。promise

正常的Future在jdk中的使用方法,Future針對的就是一個task,task每每是一個runnable,Future和runnable在一塊兒,他就是一個task。異步

FutureTask<String> future=new FutureTask<>(task);函數式編程

executor.execute(future);函數

把future放在execute裏面,執行的是runnable對象,只不過是用Future管理了一下。Task裏面須要設定狀態,Future是針對要執行的任務的封裝,對任務作了一個加強的操做。可是netty裏面的future,這些方法是不夠的。因此添加了一些接口,並且是異步的操做。ui

jdk裏面的Future是isDone,沒有判斷是否成功,只判斷了是否取消了(isCalled),netty裏面的future是isSuccess,還加了是否能夠取消。是對狀態判斷的補充。cause方法,拋出異常以後能夠知道是怎樣跑出的什麼異常。netty的future,很核心的一個方法:addListener,經過isDone判斷這個future結束了,結束了以後立馬喚醒這個listener。至關於就是一個回調。netty

有增長通常就有刪除,因此有removeListener。對象

future須要特別注意的方法有三個,isDone,isSuccess,addListener。blog

知道這個以後,再來講一下函數式編程,函數式編程會強調一個promise。就是成功以後會作什麼事,失敗以後會作什麼事。promise和響應式編程很像,有onNext,onComplete,onError這幾種處理,你有元素下發的時候怎麼處理,當你正常結束的時候怎麼處理,當出錯的時候怎麼處理。咱們的正常使用只是一個地址的訪問,給我返回結果,咱們只須要對結果進行判斷它是成功仍是失敗。若是隻須要考慮這2種,使用promise就能夠了。因此future又拓展了一個promise。

如何判斷是isSuccess,promise提供了setSuccess,trySuccess,標記爲success同時通知全部的listener。

promise接口繼承自future,因此它重寫了一些方法,把返回值有Future改成了Promise。以addListener爲例,在函數式編程中,添加的是一個動做,操做的是Future,很明顯是一個函數式接口,就是結束以後應該作什麼,只不過標記了是EventListener。EventListener是一個標記,並無設定方法。

在netty中是如何使用的,咱們更多的是針對channel,能夠以channel爲例,來分析promise一些比較核心的用法。

首先有個接口,ChannelPromise,一樣ChannelPromise返回的都是ChannelPromise,它繼承ChannelFuture和Promise。

而後來看一下ChannelFuture的默認使用:DefaultChannelFuture

他繼承自DefaultPromise,先看一下DefaultPromise:

先看addListener方法,addListener是一個動做,它須要作一些事情。

一個是添加進去,addListener0,添加進去確定是要作管理的,那如何管理,要麼是容器要麼是鏈表。

那這個裏面,DefaultFutureListener裏面是一個容器,一個數組,只不過是限定了類型。

addListener作了2件事,一個是作添加,添加完以後,就要作判斷這個task是否已經結束了。jdk中的Future的一個核心方法之一就是isDone().人物的結束與否並非看你是否返回告終果,而是看isDone,因此在作任何事以前,先判斷是否isDone。假如結束以後就notifyListeners(),之因此說addListener它是一個回調,是由於notifyListeners能夠拿到一個executer,而後作事情。

對listener進行遍歷,而後執行。咱們管理了一個針對Future的動做。

監聽器就是一個回調,只不過作了相應的封裝。

因此在添加listener的時候,必定要注意有一個isDone的判斷。

看一下DefaultPromise的isDone():

假如咱們並無設置值的話,result就是null,他只不過傳入了一個Object。它並無限定類型,能夠放DefaultPromise的V類型,一樣也能夠只是一個Object,管理幾種裝態,這個isDone只是表明結束了,並非表明成功了。

isDone以後,須要作isSuccess的判斷。那isSuccess應該放在哪一塊去作呢?

仍是看DefaultPromise:

默認狀況下它是成功或者有值的。

而後來看一下DefaultChannelFuture的setSuccess方法:

setSuccess爲null,而後trySuccess也是null。

若是你傳的是null,就設置爲SUCCESS.設置完以後就是一個通知的回調。

而後看一下他們常見的調用:

設置爲success狀態以後返回,在使用的時候只須要點addListener便可,就直接去執行listener中的動做了。

pool.acquire()已經把success設置進去了,因此只須要addListener便可。他的isDone就結束了。因此addLIstener就直接去執行相關的代碼了。

一樣的,獲取鏈接也是先去判斷是否isDone,結束了的話,就作結束以後的動做,

首先我本身定義了一個promise,你拿到這個channel,放到這個promise裏面,外層的話,就能夠作到一個控制。在這一起,直接加一個listener就好了。用的就是netty的一向的套路。

在使用future的使用,經過這種方式,咱們學會使用addListener,咱們要指導addListener要通過哪些操做,第一步添加,第二步,經過isDone判斷是否結束了,結束了的話,就作一些事,isDone後面緊跟的就是isSuccess,我是否是成功設定了,成功了的話,我纔會去取。假如失敗的話,就tryFuture,若是有異常的話,就future.cause().

接着咱們在看一下其餘的代碼,

config().group().register(channel)獲得一個ChannelFuture,若是要判斷isDone,再判斷isSuccess,不如直接判斷cause()是否爲null,不爲null,再判斷是否註冊了,沒有註冊成功的話,就close,沒有異常直接返回去,不會作任何其餘的動做。

學過nio的就應該知道,註冊其實仍是要經過channel.register()來實現。

它經過ChannelPromise把Channel包裹進來,而後它就能夠拿到當前的selector,

因此能夠把promise當作一個針對channel的動做。

相關文章
相關標籤/搜索