Guava의 EventBus를 사용하여 일부 처리 및 결과보고를 시작합니다.Guava EventBus dispatching
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은 다음과 같습니다. 이미 최상위 InitiateProcessing
이벤트, 단지 큐의 끝에 얻을수 이벤트의 나머지 부분을 파견하고있어 이후 무슨 일
/**
* 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)
이다. 모든 .NET 핸들러가 완료 될 때까지 이벤트를 호출하지 않는 .NET 이벤트와 비슷한 동작을하고 싶습니다.
이 구현에 대한 이유를 이해하지 못합니다. 물론 이벤트는 순서대로 보장되지만 주변 코드의 순서는 완전히 왜곡됩니다.
버스가 설명 된대로 작동하고 원하는 출력을 낼 수있는 방법이 있습니까? I는 Javadoc과의 EventBus이 방법은 명시 적으로 @AllowConcurrentEvents 주석을 함유하여 을 허용하지 않으면이 동시에 여러 스레드에서 가입자 메소드를 호출하지 않을 것이라는 보장
것을 읽었다.
하지만 여기서는 이것이 적용되지 않는다고 생각합니다. 단일 스레드 응용 프로그램에서이 문제를보고 있습니다.
편집
여기에 문제의 원인은 내가 가입자 내에서 보내고 post
해요 있다는 것입니다. 이벤트 버스는 재 입력이 아니므로 이러한 "하위 게시물"은 대기열에 올라서 첫 번째 처리기가 완료된 후에 처리됩니다. 내가섹션에서 언급 할 수 있으며, 모든 것이 예상대로 작동합니다. 그래서 실제 질문은 내가 제기 한 잠재적 인 문제점을 어떻게 알았습니까? 디자이너는 재진입을 허용하지 않기 위해 양심적 인 결정을 한 것 같습니다.
은 이벤트 버스가 자체 스레드에서 실행되는 것처럼 보입니다. 즉, 액션은 비동기 적으로 수행되고 (곧 버스 임), 명령에 따라 전달되도록 보장되며 메인 스레드와 아무런 관련이 없음을 의미합니다. – injecteer
@injecteer 자체 스레드를 실행하지 않습니다. 그들은 당신이'Executor'를 지정할 수있게 해주는'AsyncEventBus'를 가지고 있습니다 -하지만 그것을 사용하지는 않습니다. 이것은 모두 단일 스레드입니다. – zmb
당신이 옳을 수도 있습니다. 내 생각에 그들은 새로운 스레드에서 실행한다 :) 당신은 각각의 처리에'System.out.println ("curr thread :"+ Thread.currentThread(). getName())' @ Subscribe'-d 메소드? – injecteer