Guava包学习--EventBus
之前没用过这个EventBus,然后看了一下EventBus的源码也没看明白,(-__-)b。反正大概就是弄一个优雅的方式实现了观察者模式吧。慢慢深入学习一下。
观察者模式其实就是生产者消费者的一个变种,就是一边有变化,然后有一个中介,也就是观察者去告诉消费者说:我说哥们啊,他们那边又变了,咱也跟着变吧!
然后观察者要么就是一个抽象类或者一个接口,里面有个update方法,需要每个处理的实例去实现,然后变化的那方持有这些实例,然后挨个去通知。
所以你也看到了,这个持有操作其实就是很不优雅的操作,所以我们用EventBus来看下这个地方到底是怎么实现的优雅的:

可以看到其实Guava中的EventBus的代码很少,只有几个类和注解。
注解有俩个:AllowConcurrentEvents和Subscribe,@AllowConcurrentEvents代表使用线程安全方式获得通知和@Subscribe代表这是一个订阅者,这俩注解和一起使用。
EventBus也就是观察者角色类有两个 EventBus和AsyncEventBus,前面是同步消息,后面支持异步消息。
DeadEvent是指没人关心的消息,可以做一下特殊处理,这个还是很有用,你可以获得有哪些消息根本没人消费过。
Subscriber订阅者对象,具体是哪个EventBus、哪个Listener、哪个方法 3者共同决定一个Subcriber
Dispatcher分发消息给上面那个(那些)Subscriber
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]
Guava包学习--EventBus的更多相关文章
- Guava包学习---Lists
Guava包是我最近项目中同事推荐使用的,是google推出的库.里面的功能非常多,包括了集合.缓存.原生类型支持.并发库.通用注解.字符串处理.IO等.我们项目中使用到了guava依赖,但是实际上只 ...
- Guava包学习-Cache
这段时间用到了ehcache和memcache,memcache只用来配置在tomcat中做负载均衡过程中的session共享,然后ehcache用来存放需要的程序中缓存. Guava中的Cache和 ...
- Guava包学习---Maps
Maps包方法列表: 还是泛型创建Map: public static <K, V> HashMap<K, V> newHashMap() { return new HashM ...
- Guava包学习--Hash
我们HashMap会有一个rehash的过程,为什么呢?因为java内建的散列码被限制为32位,而且没有分离散列算法和所作用的数据,所以替代算法比较难做.我们使用HashMap的时候它自身有一个reh ...
- Guava包学习---I/O
Guava的I/O平时使用不太多,目前项目原因导致基本上只有在自己写一些文本处理小工具才用得到.但是I/O始终是程序猿最常遇到的需求和面试必问的知识点之一.同时Guava的I/O主要面向是时JDK5和 ...
- Guava包学习---Bimap
Bimap也是Guava中提供的新集合类,别名叫做双向map,就是key->value,value->key,也就是你可以通过key定位value,也可以用value定位key. 这个场景 ...
- Guava包学习-Multimap
它和上一章的MultiSet的继承结果很相似,只不过在上层的接口是Multimap不是Multiset. Multimap的特点其实就是可以包含有几个重复Key的value,你可以put进入多个不同v ...
- Guava包学习---Sets
Sets包的内容和上一篇中的Lists没有什么大的区别,里面有些细节可以看一下: 开始的创建newHashSet()的各个重载方法.newConcurrentHashSet()的重载方法.newTre ...
- Guava包学习--Table
Table,顾名思义,就好像HTML中的Table元素一样,其实就是行+列去确定的值,更准确的比喻其实就是一个二维矩阵. 其实它就是通过行+列两个key去找到一个value,然后它又containsv ...
随机推荐
- WinForm-SuspendLayout、ResumeLayout、PerformLayou——转载
WinForm-SuspendLayout.ResumeLayout.PerformLayou——转载 https://www.cnblogs.com/si-shaohua/archive/2011/ ...
- JavaScript三大对象详细解说
Js三大对象 一 浏览器对象 浏览器窗口.文档document.URL地址等 常用的浏览器对象: 浏览器对象的分层结构 Window对象 (1) 属性 名称 说明 document 表示给定浏览器窗口 ...
- jQuery基础---动画效果
内容摘要: 1.显示.隐藏 2.滑动.卷动 3.淡入.淡出 4.自定义动画 5.列队动画方法 6.动画相关方法 7.动画全局属性 发文不易,转载请注明出处~ 一.显示.隐藏 jQuery 中显示方法 ...
- Bundle传递数据,Handler更新UI
Bundle主要用于传递数据:它保存的数据,是以key-value(键值对)的形式存在的. Bundle经常使用在Activity之间或者线程间传递数据,传递的数据可以是boolean.byte.in ...
- Hibernate入门(三)—— 一对多、多对多关系
一.一对多关系 1.概念 一对多关系是关系型数据库中两个表之间的一种关系.通常在数据库层级中,两表之间是有主外键关系的.在ORM中,如何通过对象描述表之间的关系,是ORM核心. 2.Hiberna ...
- Oracle数据库采用数据泵方式导入导出数据
特别说明:Oralce的数据泵导入导出技术只能用在数据库服务器上,在只有客户端的机器上是无法使用数据泵技术的. 1.创建备份文件目录 mkdir d:\dmp 2.在Oralce中注册该目录,将目录 ...
- Python 批量修改文件名并移动文件到指定目录
# -*- coding: utf-8 -*- import os, sys,re,shutil from nt import chdir #读取中文路径 u'' path=u"D:\\zh ...
- 远景GIS云上线
没有发布会.没有嘉宾.没有掌声,趁着国庆假期悄悄地将系统部署到服务器上线运行. 远景GIS云(RGIS Cloud)基于自主研发的远景GIS基础平台开发,目前已实现了Shape上传和导出.符号配置.动 ...
- LintCode2016年8月8日算法比赛----等价二叉树
等价二叉树 题目描述 检查两棵二叉树是否等价.等价意思是说,首先两棵二叉树必须拥有相同的结构,并且每个对应位置上的节点上的数据相等. 样例 1 1 / \ / \ 2 2 and 2 2 / / 4 ...
- Visual Studio解决方案vs2005/vs2008/vs2010/vs2012/vs2013/vs2015版本互相转换工具
原文:http://blog.csdn.net/xiejiashu/article/details/52397641 本文转自EasyDarwin团队成员Alex的博客:http://blog.c ...