EventBus原理深度解析
一、問題描述
在工作中,經常會遇見使用非同步的方式來發送事件,或者觸發另外一個動作:經常用到的框架是MQ(分散式方式通知)。如果是同一個jvm裡面通知的話,就可以使用EventBus。由於EventBus使用起來簡單、便捷,因此,工作中會經常用到。深入理解該框架的原理就很有必要。
二、框架解析
2.1、組織結構
eventbus的組織結構如下:
eventbus主要有以下幾部分組成:
1、eventbus、asyncEventBus:事件傳送器。
2、event:事件承載單元。
3、SubscriberRegistry:訂閱者註冊器,將訂閱者註冊到event上,即將有註解Subscribe的方法和event繫結起來。
4、Dispatcher:事件分發器,將事件的訂閱者呼叫來執行。
5、Subscriber、SynchronizedSubscriber:訂閱者,併發訂閱還是同步訂閱。
2.2、執行原理
1、eventbus是基於註冊監聽的方式來執行的,因此,首先需要將eventbus,然後才會有事件及監聽者。新建eventbus或者AsyncEventBus的方式如下:
或者
2、註冊監聽者。
底層就是將類eventListener中所有註解有Subscribe的方法與其Event對放在一個map中(一個event可以對應多個Subscribe的方法)。實現如下:
3、事件傳送:執行指定事件型別的訂閱者(包含了method),從訂閱者中獲取指定事件的訂閱者,然後按照規則(同步、非同步)執行指定的方法。
上述程式碼說明,如果事件沒有監聽者,就當作死亡事件來對待。
這裡就說明,最後就是被訂閱的方法被呼叫。
4、EventBus與AsyncEventBus的區別
從字面上看,AsyncEventBus是非同步的EventBus,那麼EventBus應該就是同步的了。EventBus的executor為MoreExecutors.directExecutor(),其實現如下:
其execute方法直接執行執行緒的run方法,即同步呼叫run方法執行。EventBus的dispatcher為PerThreadQueuedDispatcher。其dispatch方法如下:
dispatchEvent的實現如下:
因此,整個執行過程如下:
整個過程都是同步方式執行,因此,EventBus是同步的。
AsyncEventBus的dispatcher為LegacyAsyncDispatcher,executor為自己指定的執行緒池。執行流程如下:
虛線為執行緒池非同步排程,因此,AsyncEventBus為非同步方式。
5、AllowConcurrentEvents的作用
它所在的程式碼為:
即如果訂閱者方法上有註解AllowConcurrentEvents,則返回Subscriber,否則,返回SynchronizedSubscriber。SynchronizedSubscriber的字面意思為同步訂閱者,它的實現程式碼為:
即沒有使用註解AllowConcurrentEvents的訂閱者,在併發環境中,都是序列執行。這在高併發環境中,會嚴重影響效能。
三、使用案例
3.1、eventbus定義
3.2、註冊與事件傳送
3.3、訂閱者定義
四、注意事項
1、在高併發的環境下使用AsyncEventBus時,傳送事件可能會出現異常,因為它使用的執行緒池,當執行緒池的執行緒不夠用時,會拒絕接收任務,就會執行執行緒池的拒絕策略,如果需要關注是否提交事件成功,就需要將執行緒池的拒絕策略設為丟擲異常,並且try-catch來捕獲異常。如下:
2、本文用到的guava版本如下:
本文來自雲棲社群合作伙伴“開源中國”
本文作者:王練
ofollow,noindex">原文連結