맵이 키와 유형별 같은 이벤트에 대한 이벤트 리스너의 목록을 보유하고있는에서 넣어왔다 다른 스레드에서 항목을 제거 할 수 있도록하는 데 도움을으로 CopyOnWriteArrayList 수 있습니다 지도를 만들고 모든 리스너와 함께 이벤트를 처리하도록 목록을 반복합니다.는</p> <p><code>func_1()</code>는 한 종류의 listenerlist에서 얻을 시작하는 반복자
한 명의 청취자가 처리를 완료하면지도의 listener 목록에서 제거하도록 요청합니다.
청취자가 반복기에 있으므로 원래 목록에서 제거하면 iterator.previous()
의 java.util.ConcurrentModificationException
이 다음 청취자가됩니다.
질문 : 목록의 사본이기 때문에 CopyOnWriteArrayList를 사용하여 수신기 목록을 복사 한 다음 반복자를 복사하면 수신기가 다른 스레드에서 제거 될 때 여전히 throw됩니까?
이터레이터에 CopyOnWriteArrayList
대신 일반 목록을 복사하는 것만으로 차이가 있습니까?
func_1(Event event) {
List<WeakReference<EventListener<Event>>> listenerlist = mEventMap.get(event.eventType);
/* instead of directly iterator on the listenerlist
ListIterator<WeakReference<EventListener<Event>>> listenerIterator =
listenerlist.listIterator(listenerlist.size());
but making a CopyOnWriteArrayList first:
*/
List<WeakReference<EventListener<Event>>> listeners =
new CopyOnWriteArrayList<>(listenerlist);
ListIterator<WeakReference<EventListener<Event>>> listenerIterator =
listeners.listIterator(listeners.size());
while(listenerIterator.hasPrevious()){
WeakReference<EventListener<Event>> listenerItem =
listenerIterator.previous();
//doing something
listenerItem.func_2(event);
}
}
EventListener::func_2(Event event){
//do something
//remove the type in the map
funct_3(EventListener.this);
}
funct_3(EventListener listener) {
List<WeakReference<EventListener<Event>>> listeners =
mEventMap.get(listener.eventType);
if (listeners != null) {
Iterator<WeakReference<EventListener<Event>>> listenerIterator =
listeners.iterator();
while (listenerIterator.hasNext()) {
WeakReference<EventListener<Event>> listenerItem = listenerIterator.next();
if (listenerItem.get() != null && listenerItem.get() == listener) {
listenerIterator.remove();
break;
}
}
}
}
테스트하기가 쉽지만, CopyOnWriteArrayList는 결코 ConcurrentModificationException을 throw합니다. – shmosel