之前没用过这个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的动作

我们来测试一下代码:

  1. public class EventBusMain {
  2. static final EventBus LINE_1St = new EventBus("first");
  3. static AsyncEventBus LINE_2Ed = new AsyncEventBus("second", new Executor() {
  4. @Override
  5. public void execute(Runnable command) {
  6. try {
  7. Thread.sleep(10000L);
  8. command.run();
  9. } catch (InterruptedException e) {
  10. System.out.println(e);
  11. }
  12. }
  13. });
  14.  
  15. public static void main(String[] args) {
  16. LINE_1St.register(new EventListener());
  17. LINE_2Ed.register(new EventListener());
  18.  
  19. int cpuNums = Runtime.getRuntime().availableProcessors();
  20. ExecutorService executorService = Executors.newFixedThreadPool(cpuNums * 1);
  21.  
  22. Thread thread1 = new Thread() {
  23. @Override
  24. public void run() {
  25. PromoEvent promoEvent = genPromoEvent();
  26. LINE_1St.post(promoEvent);
  27. }
  28. };
  29. Thread thread2 = new Thread() {
  30. @Override
  31. public void run() {
  32. LINE_2Ed.post(genDimensionEvent());
  33. }
  34. };
  35.  
  36. Thread thread3 = new Thread() {
  37. @Override
  38. public void run() {
  39. try {
  40. Thread.sleep(5000);
  41. LINE_1St.post(111);
  42. } catch (InterruptedException e) {
  43. e.printStackTrace();
  44. }
  45. }
  46. };
  47. executorService.execute(thread1);
  48. executorService.execute(thread2);
  49. executorService.execute(thread3);
  50. }
  51.  
  52. static PromoEvent genPromoEvent() {
  53. PromoEvent event = new PromoEvent(1, Lists.newArrayList(1L, 2L, 3L), System.currentTimeMillis(), 0L);
  54. return event;
  55. }
  56.  
  57. static DimensionEvent genDimensionEvent() {
  58. DimensionEvent event = new DimensionEvent(100, Lists.newArrayList(100L, 200L, 300L), System.currentTimeMillis(), 0L);
  59. return event;
  60. }

然后有两个自定义事件内容,基本上内容是一样的,只是用来测试:

  1. public class PromoEvent {
  2. private int activityId;
  3. private List<Long> productIds;
  4. private Long currentTime;
  5. private Long triedTimes;
  6.  
  7. /**
  8. * @param activityId
  9. * @param productIds
  10. * @param currentTime
  11. * @param triedTimes
  12. */
  13. public PromoEvent(int activityId, List<Long> productIds, Long currentTime, Long triedTimes) {
  14. super();
  15. this.activityId = activityId;
  16. this.productIds = productIds;
  17. this.currentTime = currentTime;
  18. this.triedTimes = triedTimes;
  19. }
  20.  
  21. public int getActivityId() {
  22. return activityId;
  23. }
  24.  
  25. public void setActivityId(int activityId) {
  26. this.activityId = activityId;
  27. }
  28.  
  29. public List<Long> getProductIds() {
  30. return productIds;
  31. }
  32.  
  33. public void setProductIds(List<Long> productIds) {
  34. this.productIds = productIds;
  35. }
  36.  
  37. public Long getCurrentTime() {
  38. return currentTime;
  39. }
  40.  
  41. public void setCurrentTime(Long currentTime) {
  42. this.currentTime = currentTime;
  43. }
  44.  
  45. public Long getTriedTimes() {
  46. return triedTimes;
  47. }
  48.  
  49. public void setTriedTimes(Long triedTimes) {
  50. this.triedTimes = triedTimes;
  51. }
  52.  
  53. @Override
  54. public String toString() {
  55. return "EventTest [activityId=" + activityId + ", productIds=" + productIds + ", currentTime=" + currentTime + ", triedTimes=" + triedTimes
  56. + "]";
  57. }

事件监听:

  1. public class EventListener {
  2. private PromoEvent lastPromoMessage = null;
  3. private DimensionEvent lastDimensionMessage = null;
  4. private DeadEvent deadEvent = null;
  5.  
  6. @Subscribe
  7. public void listen(PromoEvent event) {
  8. lastPromoMessage = event;
  9. System.out.println("~~~~~~~~~~PromoEvent~~~~~~~~~~~~~");
  10. System.out.println(event.toString());
  11. }
  12.  
  13. @Subscribe
  14. public void listen(DimensionEvent event) {
  15. lastDimensionMessage = event;
  16. System.out.println("----------DimensionEvent---------");
  17. System.out.println(event.toString());
  18. }
  19.  
  20. @Subscribe
  21. public void listen(DeadEvent event) {
  22. deadEvent = event;
  23. System.out.println("===========DeadEvent=============");
  24. System.out.println(event.toString());
  25. }
  26.  
  27. public PromoEvent getLastPromoMessage() {
  28. return lastPromoMessage;
  29. }
  30.  
  31. public DimensionEvent getLastDimensionMessage() {
  32. return lastDimensionMessage;
  33. }
  34.  
  35. public DeadEvent getDeadEvent() {
  36. return deadEvent;

我们声明了两个Bus总线,用来分别存放消息体:

  1. static final EventBus LINE_1St = new EventBus("first");
  2. static AsyncEventBus LINE_2Ed = new AsyncEventBus("second", new Executor() {····});

然后声明3个线程,分别往同步总线里面放一个消息;延迟5秒往同步线程里面放一个无效消息;然后向延迟10秒的异步线程里面放一条消息;

然后监听器Listener分别处理这几个消息,下面是输出结果:

  1. ~~~~~~~~~~PromoEvent~~~~~~~~~~~~~
  2. EventTest [activityId=1, productIds=[1, 2, 3], currentTime=1453096744555, triedTimes=0]
  3. ===========DeadEvent=============
  4. com.google.common.eventbus.DeadEvent@4ffa5d1a
  5. ----------DimensionEvent---------
  6. EventTest [activityId=100, productIds=[100, 200, 300], currentTime=1453096744555, triedTimes=0]

  

Guava包学习--EventBus的更多相关文章

  1. Guava包学习---Lists

    Guava包是我最近项目中同事推荐使用的,是google推出的库.里面的功能非常多,包括了集合.缓存.原生类型支持.并发库.通用注解.字符串处理.IO等.我们项目中使用到了guava依赖,但是实际上只 ...

  2. Guava包学习-Cache

    这段时间用到了ehcache和memcache,memcache只用来配置在tomcat中做负载均衡过程中的session共享,然后ehcache用来存放需要的程序中缓存. Guava中的Cache和 ...

  3. Guava包学习---Maps

    Maps包方法列表: 还是泛型创建Map: public static <K, V> HashMap<K, V> newHashMap() { return new HashM ...

  4. Guava包学习--Hash

    我们HashMap会有一个rehash的过程,为什么呢?因为java内建的散列码被限制为32位,而且没有分离散列算法和所作用的数据,所以替代算法比较难做.我们使用HashMap的时候它自身有一个reh ...

  5. Guava包学习---I/O

    Guava的I/O平时使用不太多,目前项目原因导致基本上只有在自己写一些文本处理小工具才用得到.但是I/O始终是程序猿最常遇到的需求和面试必问的知识点之一.同时Guava的I/O主要面向是时JDK5和 ...

  6. Guava包学习---Bimap

    Bimap也是Guava中提供的新集合类,别名叫做双向map,就是key->value,value->key,也就是你可以通过key定位value,也可以用value定位key. 这个场景 ...

  7. Guava包学习-Multimap

    它和上一章的MultiSet的继承结果很相似,只不过在上层的接口是Multimap不是Multiset. Multimap的特点其实就是可以包含有几个重复Key的value,你可以put进入多个不同v ...

  8. Guava包学习---Sets

    Sets包的内容和上一篇中的Lists没有什么大的区别,里面有些细节可以看一下: 开始的创建newHashSet()的各个重载方法.newConcurrentHashSet()的重载方法.newTre ...

  9. Guava包学习--Table

    Table,顾名思义,就好像HTML中的Table元素一样,其实就是行+列去确定的值,更准确的比喻其实就是一个二维矩阵. 其实它就是通过行+列两个key去找到一个value,然后它又containsv ...

随机推荐

  1. WCF-绑定模型(一)

    一.利用BasicHttpBinding实现消息通信 WCF基础架构由服务模型层和信道层构成,而绑定是两层直接的纽带.绑定创建了处理消息的信道栈,实现消息的传输和处理.在绑定模型中涉及很多通信对象,信 ...

  2. winform从table1获取需要的数据转存储到table2中

    小技术一个,记录一下 ,以下记录的是用两种方式来实现,数据表的转移 table转存数据之前首先要明确两个函数: Add():是指在最后一行添加一行 InsertAt():可以插入到表中的指定行 需求: ...

  3. Z_Tree的使用案例(出差地点的演示)

    1.准备工作(下载zTree并添加到项目JS中) 2.HTML代码 <link rel="stylesheet" href="./js/zTree_v3-3.5.2 ...

  4. Core.Java.Volume.I.Fundamentals.10th.Edition 14.5.8 Volatile域 中文版 章节勘误

    今天重扫了corejava 14 并发的一章,在谈到volatile域代替synchronized 应用于并发更新时,看到如下内容,并发更新可用内部锁的方式但会带来阻塞问题,可用volatile域替代 ...

  5. golang 的md5加密

    先看实现代码: package main import (     "crypto/md5"     "encoding/hex"     "fmt& ...

  6. 文件下载(Servlet/Struts2)

    文件上传(Servlet/Struts2/SpringMVC)的链接:http://www.cnblogs.com/ghq120/p/8312944.html 文件下载 Servlet实现 目录结构 ...

  7. 原型链中的prototype、__proto__和constructor的关系

    先来看一张图,这张图可以说是围绕以下代码完整的描述了各对象之间的关系.接下来我们来看看如何一步步画出这张图. function Foo(){}; var foo = new Foo(); 首先,明确几 ...

  8. js中常用的算法排序

    在工作中都会经常用到的一些基础算法,可以很快解决问题.这些都是在工作中总结的,希望可以帮助到大家. 一.数组乱序 arr.sort(function randomsort(a, b) { return ...

  9. vs code上配置Scala

    转自:https://www.cnblogs.com/steven-yang/p/5852988.html 百度的结果表达太奇怪,简单记一笔. 1.下载一个scala的压缩包,https://www. ...

  10. GIS 地理坐标分类

    wgs84 GPS系统直接通过卫星定位获得的坐标.(最基础的坐标.) gcj02 兲朝已安全原因为由,要求在中国使用的地图产品使用的都必须是加密后的坐标.这套加密后的坐标就是gcj02 google的 ...