一、说明
1、需要外部提供异步执行事件使用的线程池,对事件进行异步发送
2、实际上,尽管用异步的事件总线,也不应该占用事件发送线程处理事件,而应该由业务线程池处理,如netty的设计理念
二、代码
listener
package com.mzj.guava.eventbus.listeners;
import com.google.common.eventbus.Subscribe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 测试异步总线listener
*/
public class AsyncSimpleListener {
private final static Logger LOGGER = LoggerFactory.getLogger(AsyncSimpleListener.class);
@Subscribe
public void doAction1(final String event) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Received event [{}] and will take a action1", event);
}
}
@Subscribe
public void doAction2(final String event) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Received event [{}] and will take a action2", event);
}
}
@Subscribe
public void doAction3(final String event) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Received event [{}] and will take a action3", event);
}
}
@Subscribe
public void doAction4(final String event) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Received event [{}] and will take a action4", event);
}
}
}
main
package com.mzj.guava.eventbus.myeventbus;
import com.google.common.eventbus.AsyncEventBus;
import com.mzj.guava.eventbus.listeners.AsyncSimpleListener;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
public class AsyncEventBusExample
{
public static void main(String[] args)
{
AsyncEventBus eventBus = new AsyncEventBus(Executors.newFixedThreadPool(4));
// AsyncEventBus eventBus = new AsyncEventBus(new SeqExecutor());
eventBus.register(new AsyncSimpleListener());
eventBus.post("hello");
}
static class SeqExecutor implements Executor
{
@Override
public void execute(Runnable command)
{
command.run();
}
}
}
三、源码
AsyncEventBus的实现代码仅此而已:
package com.google.common.eventbus;
import com.google.common.annotations.Beta;
import java.util.concurrent.Executor;
@Beta
public class AsyncEventBus extends EventBus {
public AsyncEventBus(String identifier, Executor executor) {
super(identifier, executor, Dispatcher.legacyAsync(), LoggingHandler.INSTANCE);
}
public AsyncEventBus(Executor executor, SubscriberExceptionHandler subscriberExceptionHandler) {
super("default", executor, Dispatcher.legacyAsync(), subscriberExceptionHandler);
}
public AsyncEventBus(Executor executor) {
super("default", executor, Dispatcher.legacyAsync(), LoggingHandler.INSTANCE);
}
}
可见,通过抽象executor,使得AsyncEventBus可以继承EventBus 进行实现
四、补充
- google eventbus的异步特征,是由构造eventbus时提供的Executor决定的,也就是new AsyncEventBus时,如果传递个single executor或者runnable->{ runnable.run(); }的lambda,创建出来的eventbus仍然是串行的。
- google eventbus设计上优化建议1:上面一点封装性不是太好,如果使用ExecutorService就没问题
- google eventbus设计上优化建议2:executor使用完毕后需要外部自行关闭,最好是eventbus提供一个方法供外部调用释放资源,虽然executor是外部创建好提供的,从职责上属于外部,但是如果释放资源也由外部释放,则外部不清楚close时,eventbus处于何种状态,而如果由eventbus进行释放,可以在释放之前做准备,比如:优雅退出、发送未处理事件等等动作。