У меня есть класс EventBus для добавления / удаления обработчика и отправки события обработчикам:
public class EventBus{
private Map<Integer,List<EventHandler>> handlers = new HashMap<>();
private static EventBus ourInstance = new EventBus();
public static EventBus getInstance(){
return ourInstance;
}
public <T extends EventHandler> void fireEvent(Event<T> event){
int hash = event.getAssociatedType().hashCode();
List<EventHandler> handlersSublist = handlers.get(hash);
if(handlersSublist != null){
System.out.println("I have " + handlersSublist.size() + " handlers for event " + hash);
for(EventHandler handler : handlersSublist){
System.out.println("Fire event " + hash + " to " + handler.getClass().getName().toString());
event.dispatch((T)handler);
}
}
}
public <T> void addHandler(Event.Type<T> type, EventHandler handler){
Integer hash = type.hashCode();
List<EventHandler> handlersSublist = handlers.get(hash);
if(handlersSublist == null){
handlersSublist = new ArrayList<>();
handlers.put(hash,handlersSublist);
}
System.out.println("Add " + handler.getClass().getName().toString() + " for event " + hash);
handlersSublist.add(handler);
}
public <T> void removeHandler(Event.Type<T> type, EventHandler handler) {
Integer hash = type.hashCode();
List<EventHandler> handlersSublist = handlers.get(hash);
if (handlersSublist != null) {
System.out.println("Remove " + handler.getClass().getName().toString() + " for event " + hash);
handlersSublist.remove(handler);
}
}
}
У меня есть AEventHandler, который слушает AEvent. Когда запускается AEvent, данный обработчик выполняет некоторые действия и удаляется из eventBus:
public class AEventHandlerImpl1 implements AEventHandler
{
@Override
public void onAEventReceived(AEvent aEvent)
{
//do some stuff...
//... and remove myself from the bus for AEvent
EventBus.getInstance().removeHandler(AEvent.TYPE, this);
}
}
В моем основном методе я создаю 2 обработчика, добавляю их в шину для прослушивания AEvent и запускаю событие AEvent:
public static void main(String[] args)
{
System.out.println("-= START =-");
//create new handlers
AEventHandlerImpl1 handler1 = new AEventHandlerImpl1();
AEventHandlerImpl1 handler2 = new AEventHandlerImpl1();
//add handlers on the eventBus
EventBus.getInstance().addHandler(AEvent.TYPE, handler1);
EventBus.getInstance().addHandler(AEvent.TYPE, handler2);
//fire event
EventBus.getInstance().fireEvent(new AEvent());
//end
System.out.println("-= END =-");
}
Результат:
-= START =-
Add be.test.AEventHandlerImpl1 for event 1
Add be.test.AEventHandlerImpl1 for event 1
I have 2 handlers for event 1
Fire event 1 to be.test.AEventHandlerImpl1
Remove be.test.AEventHandlerImpl1 for event 1
-= END =-
Метод отправки никогда не вызывается для второго обработчика. Это потому, что первый обработчик удаляет себя из шины (из handlersSublist) во время выполнения оператора цикла. Я решил эту проблему зацикливанием на копии handlersSublist, а не на самом handlersSublist. Но вопрос в том, почему я не получаю ConcurrentModificationException
? Я изменяю ArrayList
во время цикла. В этом потоке пользователь 1947415 получил ConcurrentModificationException
, когда удалил первый элемент списка. В этом потоке пользователь 1699872 не получил исключения. потому что он использовал Iterator
для цикла по списку. В чем дело? Почему я не получаю ConcurrentModificationException
, поскольку я не использую Iterator
и удаляю первый элемент списка?
Может кто-нибудь объяснить мне, почему?
Заранее спасибо,
EventBus
методfireEvent
. - person zatenzu   schedule 10.09.2015fireEvent
? - person learningloop   schedule 10.09.2015removeHandler()
в методеonAEventReceived()
классаAEventHandlerImpl1
и добавлю handlersSublist.remove (обработчик) в методfireEvent()
сразу после вызова event.dispatch (), я получу тот же результат, без исключения. - person zatenzu   schedule 10.09.2015