我使用Guava的EventBus启动一些处理和报告结果。这里是一个非常简单的编译例子:Guava EventBus调度
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
public class Test {
public static class InitiateProcessing { }
public static class ProcessingStarted { }
public static class ProcessingResults { }
public static class ProcessingFinished { }
public static EventBus bus = new EventBus();
@Subscribe
public void receiveStartRequest(InitiateProcessing evt) {
System.out.println("Got processing request - starting processing");
bus.post(new ProcessingStarted());
System.out.println("Generating results");
bus.post(new ProcessingResults());
System.out.println("Generating more results");
bus.post(new ProcessingResults());
bus.post(new ProcessingFinished());
}
@Subscribe
public void processingStarted(ProcessingStarted evt) {
System.out.println("Processing has started");
}
@Subscribe
public void resultsReceived(ProcessingResults evt) {
System.out.println("got results");
}
@Subscribe
public void processingComplete(ProcessingFinished evt) {
System.out.println("Processing has completed");
}
public static void main(String[] args) {
Test t = new Test();
bus.register(t);
bus.post(new InitiateProcessing());
}
}
我使用这些事件作为其他软件组件的方式,准备以反应这种处理。例如,他们可能必须在处理之前保存其当前状态并在之后进行恢复。
我希望这个程序的输出是:
Got processing request - starting processing
Processing has started
Generating results
got results
Generating more results
got results
Processing has completed
相反,实际的输出是:
Got processing request - starting processing
Generating results
Generating more results
Processing has started
got results
got results
Processing has completed
是应该指出的处理已经开始实际发生后,事件实际处理(“生成结果”)。
看过源代码后,我明白为什么它会这样做。以下是EventBus
的相关source code。
/**
* Drain the queue of events to be dispatched. As the queue is being drained,
* new events may be posted to the end of the queue.
*/
void dispatchQueuedEvents() {
// don't dispatch if we're already dispatching, that would allow reentrancy
// and out-of-order events. Instead, leave the events to be dispatched
// after the in-progress dispatch is complete.
if (isDispatching.get()) {
return;
}
// dispatch event (omitted)
发生了什么事,因为是我已经派遣顶级InitiateProcessing
事件,一下就被推到了队列的末尾事件的其余部分。我希望它的行为类似于.NET事件,在所有处理程序完成之前调用该事件不会返回。
我不太明白这个实现的原因。当然,这些事件保证是有序的,但是周围代码的顺序会被完全扭曲。
是否有任何方式让公共汽车按照所述的方式运行并产生所需的输出?我没在的Javadoc读取
的EventBus保证它不会同时从多个 线程调用用户的方法,除非法明确允许 它由轴承@AllowConcurrentEvents注解。
但我不认为这适用于此 - 我在单线程应用程序中看到此问题。
编辑
这里的问题的原因是,我post
从用户中荷兰国际集团。由于事件总线不可重入,这些“子帖子”排队等待并在第一个处理程序完成后处理。我可以在EventBus
源文件中注释if (isDispatching.get()) { return; }
部分,并且所有内容都按我的预期行事 - 所以真正的问题是我通过这样做引入了哪些潜在问题?看起来设计师做出了一个不让重入的认真决定。
看起来像事件总线运行在它自己的线程。这通常意味着这些操作是异步执行的,并且(尽快它是一个总线)保证按照其顺序执行,并且与主线程无关 – injecteer
@injecteer它不运行它自己的线程。他们有一个'AsyncEventBus',允许你指定一个'Executor' - 但我没有使用它。这全是单线程的。 – zmb
你可能是对的。虽然我认为,他们运行在一个新的线程:)你可以请测试它通过添加'System.out.println(“curr线程:”+ Thread.currentThread()。getName())'到每个处理' @订阅'-d方法? – injecteer