使用Guava EventBus构建publish/subscribe系统
Google的Guava类库提供了EventBus,用于提供一套组件内publish/subscribe的解决方案.事件总线EventBus,用于管理事件的注册和分发。在系统中,Subscribers会向EventBus注册自己感兴趣的事件,而publishers会将自己产生的事件发布给EventBus。在系统中,EventBus事件分发默认设置为串行的(可设置),我们在Subscribers中的事件处理速度要快,不要阻塞当前的事件纷发进程。

创建EventBus实例
EventBus提供两个构造函数,可用于创建Evnet实例,如下所示。
@Test
public void should_create_event_bus_instance() throws Exception {
EventBus eventBus = new EventBus();
//string构造参数,用于标识EventBus
EventBus eventBus1 = new EventBus("My Event Bus");
}
Subscribe事件
- Subsciber对象需要定义handler method,用于接受并处理一个通知事件对象
- 使用Subscribe标签标识事件handler method
- Subscriber向EvenetBus注册,通过EventBus.register方法进行注册
Post事件
post一个事件很简单,只需要调用EventBus.post方法即可以实现。EventBus会调用Subscriber的handler method处理事件对象。
定义handler Method
方法接受一个事件类型对象,当publisher发布一个事件,eventbus会串行的处理event-handling method, 所以我们需要让event-handing method处理的速度快一些,通常我们可以通过多线程手段来解决延迟的问题。
Concurrency
EventBus可以通过使用AllowConcurrentEvent注解来实现并发调用handle method。当handler method被标记为AllowConcurrentEvent(replace Subscribe标签),我们认为handler Method是线程安全的。
Code Sample
例子中,我们使用cookie店为例,为了简单起见,系统中只定义了五个对象:
- EmptyEvent对象:用于表明CookieContaier cookie数量为0
- CookieContaier对象:用于Cookie的存储,当cookie数量为0时,会发布EmptyEvent事件
- CookieSeller: EmptyEvent事件订阅者
- CookieMailBoss:EmptyEvent事件订阅者
- HandlerService: 定义handler-method接口,使用@Subscribe标注
public interface HandlerService {
@Subscribe
void handler(EmptyEvent emptyEvent);
}
public class CookieSeller implements HandlerService {
public CookieSeller(EventBus eventBus) {
eventBus.register(this);
}
public void handler(EmptyEvent emptyEvent) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(this.getClass().getName() + ":" + "receiving empty event");
}
}
public class CookieMallBoss implements HandlerService {
public CookieMallBoss(EventBus eventBus) {
eventBus.register(this);
}
public void handler(EmptyEvent emptyEvent) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(this.getClass().getName() + ":" + "receiving empty event");
}
}
getCookie函数,会计算事件触发publish时间
public class CookieContainer {
private EventBus eventBus;
private AtomicInteger numberOfCookie = new AtomicInteger();
public CookieContainer(EventBus eventBus) {
this.eventBus = eventBus;
}
public void setNumberOfCookie(int intenger) {
numberOfCookie.set(intenger);
}
public void getACookie() {
if (numberOfCookie.get() == 0) {
long start = System.currentTimeMillis();
eventBus.post(new EmptyEvent());
System.out.println("Publishing event time: " + (System.currentTimeMillis() - start) + " ms");
return;
}
numberOfCookie.decrementAndGet();
System.out.println("retrieve a cookie");
}
}
public class EmptyEvent {
}
Code Test Case
设置cookie数量为三,当第四次取cookie会触发empty事件,EventBus会串行的发布事件。
@Test
public void should_recv_event_message() throws Exception {
EventBus eventBus = new EventBus();
CookieContainer cookieContainer=new CookieContainer(eventBus);
HandlerService cookieSeller = new CookieSeller(eventBus);
HandlerService cookieMallBoss = new CookieMallBoss(eventBus);
//设置cookie的数量为3
cookieContainer.setNumberOfCookie(3);
//用户取三次之后cookie数量为空
cookieContainer.getACookie();
cookieContainer.getACookie();
cookieContainer.getACookie();
System.out.println("=======再次取cookie, 触发Empty事件发布============");
cookieContainer.getACookie();
}
测试结果如下所示,当第四次getCookie时,触发EmptyEvent事件发布。耗时为4013ms
retrieve a cookie
retrieve a cookie
retrieve a cookie
=======触发事件发布============
com.mj.ele.guava.CookieMallBoss:receiving empty event
com.mj.ele.guava.CookieSeller:receiving empty event
Publishing event time: 4013 ms
使用AllowConcurrentEvents标签取Subscribe,设置cookie数量为三,当第四次取cookie会触发empty事件,EventBus会并行的发布事件。
修改Handler method接口,标记为@AllowConcurrentEvents
public interface HandlerService {
@AllowConcurrentEvents
void handler(EmptyEvent emptyEvent);
}
测试代码和串行代码一致,测试结果如下所示,事件发布耗时只需1ms
retrieve a cookie
retrieve a cookie
retrieve a cookie
=======触发事件发布============
Publishing event time: 1 ms
Conclusion
本文讲解了如何使用Guava的EventBus来构建publish/subscribe系统,分别给出了串行和并行发布的使用方法,希望能够给读者带来一些帮助和启发。
使用Guava EventBus构建publish/subscribe系统的更多相关文章
- 设计模式:Observer(观察者)—— Guava EventBus
本文分为三个部分: Observer(观察者) Guava EventBus详解 Guava EventBus使用示例 1. Observer(观察者) 1.1 背景 我们设计系统时, ...
- 【RabbitMQ】Publish/Subscribe
Publish/Subscribe 在上一节我们创建了一个work queue.背后的设想为每个任务被分发给明确的消费者.这节内容我们将做一些完全不同的事情 -- 我们将发送一条消息给多个消费者.这种 ...
- RabbitMQ学习总结 第四篇:发布/订阅 Publish/Subscribe
目录 RabbitMQ学习总结 第一篇:理论篇 RabbitMQ学习总结 第二篇:快速入门HelloWorld RabbitMQ学习总结 第三篇:工作队列Work Queue RabbitMQ学习总结 ...
- (转)RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)
上篇文章中,我们把每个Message都是deliver到某个Consumer.在这篇文章中,我们将会将同一个Message deliver到多个Consumer中.这个模式也被成为 "pub ...
- 柯南君:看大数据时代下的IT架构(6)消息队列之RabbitMQ--案例(Publish/Subscribe起航)
二.Publish/Subscribe(发布/订阅)(using the Java Client) 为了说明这个模式,我们将构建一个简单的日志系统.它将包括两个项目: 第一个将发出日志消息 第二个将接 ...
- RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)
上篇文章中,我们把每个Message都是deliver到某个Consumer.在这篇文章中,我们将会将同一个Message deliver到多个Consumer中.这个模式也被成为 "pub ...
- RabbitMQ 分发到多Consumer(Publish/Subscribe)
上篇文章中,我们把每个Message都是deliver到某个Consumer.在这篇文章中,我们将会将同一个Message deliver到多个Consumer中.这个模式也被成为 "pub ...
- RabbitMQ系列教程之三:发布/订阅(Publish/Subscribe)(转载)
RabbitMQ系列教程之三:发布/订阅(Publish/Subscribe) (本教程是使用Net客户端,也就是针对微软技术平台的) 在前一个教程中,我们创建了一个工作队列.工作队列背后的假设是每个 ...
- RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)[转]
上篇文章中,我们把每个Message都是deliver(提供)到某个Consumer.在这篇文章中,我们将会将同一个Message deliver(提供)到多个Consumer中.这个模式也被成为 & ...
随机推荐
- 再见,OI
你好,NOIP 2015年9月1日 正式成为了福建省莆田一中的一名高一成员 后来学校搞了选修 大家都很激动 因为自己的兴趣和特长能够得到发挥了(或者说能逃课或者看好多电影) 发现选修提供的选项中有好几 ...
- SSH ProxyCommand
简单的说就是SSH层面的代理服务器,实现通过跳板机执行SSH相关命令到目标机器的代理服务.
- [MVC4]初识.NET MVC4
最近一个月都在专心做unity3d的斗地主游戏,从早到晚,最后总算是搞出来了,其中的心酸只有自己知道.最近才有功夫闲下来,还是学习学习之前的老本行——asp.net,现在用.net做项目流行MVC,而 ...
- 基于DevExpress实现对PDF、Word、Excel文档的预览及操作处理
http://www.cnblogs.com/wuhuacong/p/4175266.html 在一般的管理系统模块里面,越来越多的设计到一些常用文档的上传保存操作,其中如PDF.Word.Excel ...
- 【vuejs小项目——vuejs2.0版本】单页面搭建
http://router.vuejs.org/zh-cn/essentials/nested-routes.html 使用嵌套路由开发,这里会出错主要把Vue.use(VueRouter);要进行引 ...
- 【微信开发】—7200s限制,非数据库
两种微信缓存方式(7200s) 第一种是MemoryCache(缓存的分享票据) public static string Getjsapi_ticket(string AppID, string A ...
- SQLServer2005如何批量修改架构名 - wuxiaokaixinguo的专栏
原文地址:http://blog.csdn.net/wuxiaokaixinguo/article/details/8523093 ) BEGIN SET @name='原构架名.' + @name ...
- Ancient Printer[HDU3460]
Ancient Printer Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)Tot ...
- underscorejs 源码走读笔记
Underscore 简介 Underscore 是一个JavaScript实用库,提供了类似Prototype.js的一些功能,但是没有继承任何JavaScript内置对象.它弥补了部分jQuery ...
- Thisgood
this is good test print 'haha'