Guava EventBus應(yīng)用實(shí)例

來(lái)個(gè)開(kāi)頭
多多讀書(shū),珍惜時(shí)間

EventBus是guava包中的一個(gè)事件通知組件,可以用來(lái)在同一個(gè)JVM中,實(shí)現(xiàn)事件通知機(jī)制。異步和同步都有實(shí)現(xiàn)。這里和Android的EventBus不是一個(gè)事物。
在一些業(yè)務(wù)場(chǎng)景中,我們會(huì)使用Redis隊(duì)列或者Kafka等其他MQ來(lái)實(shí)現(xiàn)分布式多機(jī)器的消息通知,而EventBus是在單個(gè)JVM中使用??梢詫?duì)代碼邏輯進(jìn)行相應(yīng)的解耦,某些場(chǎng)景下,比如異步調(diào)用,可以提高整體的運(yùn)行性能。

結(jié)構(gòu)和定義

EventBus包含兩個(gè)大的模塊。第一個(gè)是發(fā)布器,第二個(gè)是訂閱器。
發(fā)布器主要是兩個(gè)方法:
1、eventBus.register(Object o)
用來(lái)注冊(cè)監(jiān)聽(tīng)器,傳入監(jiān)聽(tīng)器類型。細(xì)節(jié)是將監(jiān)聽(tīng)器有@Subscribe注解的方法和事件類型對(duì)應(yīng)到一個(gè)map里。記得之前有一個(gè)eventBus注冊(cè)多種消息類型的使用方式,這塊沒(méi)有詳細(xì)了解。
2、eventBus.post(Object o)
顧名思義就是將消息事件發(fā)送出去,最后交給有@Subscribe注解的方法去處理。多個(gè)方法可以同時(shí)處理一個(gè)消息,可以理解為多播。這在多種關(guān)聯(lián)處理的場(chǎng)景中非常有用。

訂閱器就比較簡(jiǎn)單,只有一個(gè)@Subscribe的注解。在收到對(duì)應(yīng)的消息類型之后就可以執(zhí)行方法中的邏輯。

以下代碼是一個(gè)簡(jiǎn)單的應(yīng)用例子,基于在SpringBoot上構(gòu)建。
創(chuàng)建一個(gè)bean,包括線程池和有界線程隊(duì)列。這里只是處理消息的線程池,和任務(wù)沒(méi)有直接關(guān)系。

//create a new EventBus bean
@Configuration
public class ConfigBean {

    @Bean
    public EventBus eventBus(){
        BlockingQueue<Runnable> queue = new LinkedBlockingDeque<>(100);
        ThreadPoolExecutor executor = new ThreadPoolExecutor(2,5,5, TimeUnit.SECONDS,queue);
        return new AsyncEventBus(executor);
    }
}

在service中創(chuàng)建監(jiān)聽(tīng)器,注冊(cè),發(fā)布,接收都寫(xiě)一起了。

    @Resource
    private EventBus eventBus;

    @PostConstruct
    public void init() {
        eventBus.register(this);
    }

    public void eventPost(){
        String[] strings = new String[]{"A","B"};
        eventBus.post(new LogEvent(strings[ThreadLocalRandom.current().nextInt(2)]));
    }

    @Subscribe
    public void eventA(LogEvent event){
        log.info("[event-a]=====" + event);
    }

    @Subscribe
    public void eventB(LogEvent event){
        log.info("[event-b]=====" + event);
    }

    @Data
    @AllArgsConstructor
    private class LogEvent{
        private String name;
    }

最后在Controller中加個(gè)方法,用于手動(dòng)觸發(fā),做簡(jiǎn)單驗(yàn)證。

    @GetMapping("/event")
    public String event() {
        demoService.eventPost();
        return "OK";
    }

執(zhí)行的最終結(jié)果日志:

2019-12-16 21:15:39.394  INFO 87204 --- [pool-1-thread-1] c.x.browser.alchemy.service.DemoService  : [event-a]=====DemoService.LogEvent(name=A)
2019-12-16 21:15:39.395  INFO 87204 --- [pool-1-thread-2] c.x.browser.alchemy.service.DemoService  : [event-b]=====DemoService.LogEvent(name=A)
2019-12-16 21:15:44.599  INFO 87204 --- [pool-1-thread-1] c.x.browser.alchemy.service.DemoService  : [event-a]=====DemoService.LogEvent(name=A)
2019-12-16 21:15:44.601  INFO 87204 --- [pool-1-thread-1] c.x.browser.alchemy.service.DemoService  : [event-b]=====DemoService.LogEvent(name=A)
2019-12-16 21:20:51.660  INFO 87204 --- [pool-1-thread-2] c.x.browser.alchemy.service.DemoService  : [event-a]=====DemoService.LogEvent(name=B)
2019-12-16 21:20:51.660  INFO 87204 --- [pool-1-thread-1] c.x.browser.alchemy.service.DemoService  : [event-b]=====DemoService.LogEvent(name=B)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容