以前沒用過這個EventBus,而後看了一下EventBus的源碼也沒看明白,(-__-)b。反正大概就是弄一個優雅的方式實現了觀察者模式吧。慢慢深刻學習一下。java
觀察者模式其實就是生產者消費者的一個變種,就是一邊有變化,而後有一箇中介,也就是觀察者去告訴消費者說:我說哥們啊,他們那邊又變了,咱也跟着變吧!安全
而後觀察者要麼就是一個抽象類或者一個接口,裏面有個update方法,須要每一個處理的實例去實現,而後變化的那方持有這些實例,而後挨個去通知。異步
因此你也看到了,這個持有操做其實就是很不優雅的操做,因此咱們用EventBus來看下這個地方究竟是怎麼實現的優雅的:ide
能夠看到其實Guava中的EventBus的代碼不多,只有幾個類和註解。post
註解有倆個:AllowConcurrentEvents和Subscribe,@AllowConcurrentEvents表明使用線程安全方式得到通知和@Subscribe表明這是一個訂閱者,這倆註解和一塊兒使用。學習
EventBus也就是觀察者角色類有兩個 EventBus和AsyncEventBus,前面是同步消息,後面支持異步消息。測試
DeadEvent是指沒人關心的消息,能夠作一下特殊處理,這個仍是頗有用,你能夠得到有哪些消息根本沒人消費過。this
Subscriber訂閱者對象,具體是哪一個EventBus、哪一個Listener、哪一個方法 3者共同決定一個Subcribergoogle
Dispatcher分發消息給上面那個(那些)Subscriberspa
SubscriberExceptionContext 訂閱者拋出的異常上下文
SubscriberExceptionHandler 接口,處理訂閱者拋出的異常
SubscriberRegistry 訂閱動做,處理訂閱者註冊到一個EventBus的動做
咱們來測試一下代碼:
public class EventBusMain { static final EventBus LINE_1St = new EventBus("first"); static AsyncEventBus LINE_2Ed = new AsyncEventBus("second", new Executor() { @Override public void execute(Runnable command) { try { Thread.sleep(10000L); command.run(); } catch (InterruptedException e) { System.out.println(e); } } }); public static void main(String[] args) { LINE_1St.register(new EventListener()); LINE_2Ed.register(new EventListener()); int cpuNums = Runtime.getRuntime().availableProcessors(); ExecutorService executorService = Executors.newFixedThreadPool(cpuNums * 1); Thread thread1 = new Thread() { @Override public void run() { PromoEvent promoEvent = genPromoEvent(); LINE_1St.post(promoEvent); } }; Thread thread2 = new Thread() { @Override public void run() { LINE_2Ed.post(genDimensionEvent()); } }; Thread thread3 = new Thread() { @Override public void run() { try { Thread.sleep(5000); LINE_1St.post(111); } catch (InterruptedException e) { e.printStackTrace(); } } }; executorService.execute(thread1); executorService.execute(thread2); executorService.execute(thread3); } static PromoEvent genPromoEvent() { PromoEvent event = new PromoEvent(1, Lists.newArrayList(1L, 2L, 3L), System.currentTimeMillis(), 0L); return event; } static DimensionEvent genDimensionEvent() { DimensionEvent event = new DimensionEvent(100, Lists.newArrayList(100L, 200L, 300L), System.currentTimeMillis(), 0L); return event; }
而後有兩個自定義事件內容,基本上內容是同樣的,只是用來測試:
public class PromoEvent { private int activityId; private List<Long> productIds; private Long currentTime; private Long triedTimes; /** * @param activityId * @param productIds * @param currentTime * @param triedTimes */ public PromoEvent(int activityId, List<Long> productIds, Long currentTime, Long triedTimes) { super(); this.activityId = activityId; this.productIds = productIds; this.currentTime = currentTime; this.triedTimes = triedTimes; } public int getActivityId() { return activityId; } public void setActivityId(int activityId) { this.activityId = activityId; } public List<Long> getProductIds() { return productIds; } public void setProductIds(List<Long> productIds) { this.productIds = productIds; } public Long getCurrentTime() { return currentTime; } public void setCurrentTime(Long currentTime) { this.currentTime = currentTime; } public Long getTriedTimes() { return triedTimes; } public void setTriedTimes(Long triedTimes) { this.triedTimes = triedTimes; } @Override public String toString() { return "EventTest [activityId=" + activityId + ", productIds=" + productIds + ", currentTime=" + currentTime + ", triedTimes=" + triedTimes + "]"; }
事件監聽:
public class EventListener { private PromoEvent lastPromoMessage = null; private DimensionEvent lastDimensionMessage = null; private DeadEvent deadEvent = null; @Subscribe public void listen(PromoEvent event) { lastPromoMessage = event; System.out.println("~~~~~~~~~~PromoEvent~~~~~~~~~~~~~"); System.out.println(event.toString()); } @Subscribe public void listen(DimensionEvent event) { lastDimensionMessage = event; System.out.println("----------DimensionEvent---------"); System.out.println(event.toString()); } @Subscribe public void listen(DeadEvent event) { deadEvent = event; System.out.println("===========DeadEvent============="); System.out.println(event.toString()); } public PromoEvent getLastPromoMessage() { return lastPromoMessage; } public DimensionEvent getLastDimensionMessage() { return lastDimensionMessage; } public DeadEvent getDeadEvent() { return deadEvent;
咱們聲明瞭兩個Bus總線,用來分別存放消息體:
static final EventBus LINE_1St = new EventBus("first"); static AsyncEventBus LINE_2Ed = new AsyncEventBus("second", new Executor() {····});
而後聲明3個線程,分別往同步總線裏面放一個消息;延遲5秒往同步線程裏面放一個無效消息;而後向延遲10秒的異步線程裏面放一條消息;
而後監聽器Listener分別處理這幾個消息,下面是輸出結果:
~~~~~~~~~~PromoEvent~~~~~~~~~~~~~ EventTest [activityId=1, productIds=[1, 2, 3], currentTime=1453096744555, triedTimes=0] ===========DeadEvent============= com.google.common.eventbus.DeadEvent@4ffa5d1a ----------DimensionEvent--------- EventTest [activityId=100, productIds=[100, 200, 300], currentTime=1453096744555, triedTimes=0]