Guava包學習--EventBus

以前沒用過這個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]
相關文章
相關標籤/搜索