使用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中.这个模式也被成为 & ...
随机推荐
- 【Java EE 学习 67 上】【OA项目练习】【JBPM工作流的使用】
OA项目中有极大可能性使用到JBPM框架解决流程控制问题,比如请假流程.报销流程等等. JBPM:JBoss Business Process Management,翻译过来就是业务流程管理.实际上就 ...
- ORA-12541:TNS没有监听器
cmd---services.msc----以Oracle开头TNListener结尾的服务启动它 如果还没有启动,修改注册表,Win+r,输入regedit回车,找到HKEY_LOCAL_MACHI ...
- Mac上自带的Apache介绍
Mac 自动Apache,无须再安装,默认的Apache地址是: /private/etc/apache2 一. Apache基本操作 1. 启动:sudo apachectl start 2. 查看 ...
- OpneCv2.x 模块结构
转自:http://blog.csdn.net/huang9012/article/details/21811271 之前啃了不少OpenCV的官方文档,发现如果了解了一些OpenCV整体的模块架构后 ...
- asp.net执行SqlServer存储过程!(详解!)
ASP.NET执行存储过程 一. 执行一个没有参数的存储过程的代码如下: connectionString为连接字符串 SqlConnection conn=new SqlConnection(con ...
- 【统计学习】主成分分析PCA(Princple Component Analysis)从原理到实现
[引言]--PCA降维的作用 面对海量的.多维(可能有成百上千维)的数据,我们应该如何高效去除某些维度间相关的信息,保留对我们"有用"的信息,这是个问题. PCA给出了我们一种解决 ...
- 使用CocoaPods过程中 Unable to find a specification for
文章转自:http://blog.csdn.net/zhangao0086/article/details/39703083 当把CocoaPods生成的workspace移动到上层目录时,需要改下P ...
- 使用js-xlsx库,前端读取Excel报表文件
在实际开发中,经常会遇到导入Excel文件的需求,有的产品人想法更多,想要在前端直接判断文件内容格式是否正确,必填项是否已填写 依据HTML5的FileReader,可以使用新的API打开本地文件(参 ...
- my97DatePicker日期控件——日期输入框联动,使用focus使第二个输入框没展示出日期控件
描述问题场景: 1.jquery使用的版本是jquery-1.7.2.min.js 2.代码不是写在页面上的,是通过事件后追加的 <!DOCTYPE html> <html> ...
- java反射学习之一反射机制概述
一.反射机制背景概述 1.反射(reflection)是java被视为动态语言的一个关键性质 2.反射机制指的是程序在运行时能获取任何类的内部所有信息 二.反射机制实现功能概述 1.只要给定类的全名, ...