Google Guava EventBus实例与分析

EventBus是Guava框架对观察者模式的一种实现,使用EventBus可以很简洁的实现事件注册监听和消费。Guava框架里面提供了两种相关的实现,一种是单线程同步事件消费,另外一直是多线程异步事件消费。后者在对象设计上是前者的子类。

首先我们看一个最简单的实例:

1
2
3
4
5
6
7
8
public class Event {
 
     @Subscribe
     public void sub(String message) {
         System.out.println(message);
     }
 
}

单元测试:

1
2
3
4
5
6
@Test
     public void testEventBus() {
         EventBus eventBus = new EventBus();
         eventBus.register( new Event()); //注册事件
         eventBus.post( "ssdf" ); // 触发事件处理
     }

如上所示的短短10行代码,就可以实现一个稳定的观察者模式。简单分析一下源码,调用eventBus.register(new Event())的时候,eventBus实例会将时间对象放置在SetMultimap<Class<?>, EventHandler> handlersByType中,这是一个线程安全的对象容器,卸载事件也是在这个容器中做移除操作。关键代码是eventBus.post(“ssdf”),调用post的时候,eventBus实例会将参数匹配的对象分发到事件队列(ThreadLocal<Queue<EventWithHandler>> eventsToDispatch)中,当所有事件分发完毕之后,事件队列做统一的事件消费。以上所提及的容器,队列,都是线程安全,本地线程,单线程,同步的。
如果想实现一个多线程异步出的时间容器,怎么实现能,不用担心,Guava框架提供了AsyncEventBus。单元测试代码如下:

1
2
3
4
5
6
7
@Test
     public void testAysncEventBus() {
         AsyncEventBus eventBus = new AsyncEventBus(Executors.newFixedThreadPool( 3 ));
         eventBus.register( new Event());
         eventBus.post( "ssdf" );
         System.out.println( "==" );
     }

AsyncEventBus的实现中,事件注册,卸载,都是使用的相同的逻辑。不同的处理过程在于分发事件和消费事件。事件队列使用并发安全队列替代ThreadLocal,具体的队列容器是private final ConcurrentLinkedQueue<EventWithHandler> eventsToDispatch。消费事件任务则是一个线程池,一个Executor实现,这个实现由开发者自行定义提供。
关于DeadEvent的描述,本人看了网上的一些资料,描述的不清晰,下面用一种最简单的情景进行描述。

1
2
3
4
5
6
@Test
     public void testDeadEven() {
         EventBus eventBus = new EventBus();
         eventBus.register( new Event()); // Event对象的事件方法参数是String对象
         eventBus.post( 123 ); // 使用int类型
     }

如上所示的代码,将产生一个DeadEvent,原因很简单,Event对象的@Subscribe方法是public void sub(String message) ,参数类型和post传递的参数不匹配,这将会造成Event的@Subscribe方法不被消费,这个时候,EventBus会将此Event封装成DeadEvent。

本文固定链接: http://www.xiaoyaochong.net/wordpress/index.php/2013/11/17/google-guava-eventbus%e5%ae%9e%e4%be%8b%e4%b8%8e%e5%88%86%e6%9e%90/ | 逍遥冲

猜你喜欢

转载自blog.csdn.net/liuxuejin/article/details/47728313