Java – guava eventbus scheduling
I use guava's eventbus to start some processing and report results This is a very simple compiled example:
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()); } }
I use these events as a way for other software components to react and prepare for this processing For example, they may have to save their current state before processing and restoring
I expect the output of this program to be:
Got processing request - starting processing Processing has started Generating results got results Generating more results got results Processing has completed
Instead, the actual output is:
Got processing request - starting processing Generating results Generating more results Processing has started got results got results Processing has completed
The event that should indicate the start of processing actually occurred after the actual processing ("generated result")
After reading the source code, I understand why This is the source code related to eventbus
/** * 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)
What happened is that I have published the top-level initiateprocessing event, and the rest of the events are pushed to the end of the queue I hope this is similar to The NET event does not return the event before all the processors are completed.
I don't quite understand the reason for this realization Of course, these events are guaranteed, but the order of the surrounding code is completely distorted
Is there a way for the bus to operate as described and produce the required output? I've seen it in Javadoc
But I don't think this applies here - I see this problem in a single threaded application
edit
The reason for this problem is that I publish from subscribers Since the event bus is not reentrant, these "child positions" will be queued and processed after the first handler completes I can comment out if (isdispatching. Get()) {return;} Partly in the eventbus source, everything is as I expected - so the real question is what potential problems do I introduce by doing so? The designer seems to have made a serious decision not to allow re - admission
Solution
Eventbus usually follows the principle that the code that publishes events to the bus should not care what users do to events or be respected (in the case of synchronous events)
If you want to call a specific method at a specific time of the method and want to ensure that these methods are completed before the method continues (as you are in the example), why not call these methods directly? When you use the event bus, you explicitly separate the code from the response to a given event that occurs correctly This is desirable in many cases and is the main reason for the existence of eventbus, but it does not seem to be the same