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的動做。