лучший способ объединить обработку потока событий guava и потока событий AWT - PullRequest
11 голосов
/ 01 марта 2012

Когда у вас есть асинхронная шина событий и события пожара, скажем, внутри модели, которая перехватывается в пользовательском интерфейсе, у вас, вероятно, следующая проблема:

Зарегистрированный обработчик выполняется в рабочем потоке, ноВсе изменения пользовательского интерфейса должны выполняться в потоке событий AWT.Это означает, что вам нужно обернуть все ваши обработчики в EventQueue.invokeLater(...).

Это похоже на большой код котельной плиты.Интересно, есть ли более разумное решение для этой проблемы.

Как насчет расширения шины событий гуавы, которое отмечает обработчик для выполнения в специальном потоке?Это может быть отмечено пометкой, например @ExecuteWithinEDT:

class EventBusChangeRecorder {
  @Subscribe @ExecuteWithinEDT void recordCustomerChange(ChangeEvent e) {
    recordChange(e.getChange());
  }
}

Ответы [ 2 ]

9 голосов
/ 01 марта 2012

Обработчики, зарегистрированные с помощью асинхронной шины событий, выполняются в любом потоке, который предоставленный Executor выбирает для их выполнения, не обязательно в рабочем потоке.

Я создал реализацию Executor, который запускает вещи в потоке очереди событий.Это довольно просто:

public class EventQueueExecutor implements Executor {
  @Override public void execute(Runnable command) {
    EventQueue.invokeLater(command);
  }
}

Затем вы можете просто создать свой EventBus с этим:

EventBus eventBus = new AsyncEventBus(new EventQueueExecutor());

Тогда все обработчики будут выполнены в потоке очереди событий.

Редактировать:

Пример пересылки событий:

public class EventForwarder {
  private final EventBus uiEventBus;

  public EventForwarder(EventBus uiEventBus) {
    this.uiEventBus = uiEventBus;
  }

  // forward all events
  @Subscribe
  public void forwardEvent(Object event) {
    uiEventBus.post(event);
  }

  // or if you only want a specific type of event forwarded
  @Subscribe
  public void forwardEvent(UiEvent event) {
    uiEventBus.post(event);
  }
}

Просто подпишите это на своей главной шине событий и опубликуйте все события на главной шине событий, ноподписать все компоненты пользовательского интерфейса на шину событий пользовательского интерфейса.

1 голос
/ 01 марта 2012

Вы можете создать EventBus, который отправляется только в потоке AWT:

EventBus mybus = new AsyncEventBus("awt",
    new Executor() {
        public void execute (Runnable cmd) {
            if (EventQueue.isDispatchThread()) {
                cmd.run();
            } else {
                EventQueue.invokeLater(cmd);
            }
        }
    });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...