我使用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