简体   繁体   English

没有迭代器的Java列表删除

[英]Java List Remove Without Iterator

I have an event handler system in my program where plugins can register event listeners. 我的程序中有一个事件处理程序系统,其中插件可以注册事件侦听器。
The events are called using this method. 使用此方法调用事件。

/**
 * Pass an event to registered {@link EventHandler}s.
 *
 * @param event Event to pass.
 */
public void callEvent(Event event) {
    synchronized (this) {
        HandlerList handlers = event.getHandlers();
        List<RegisteredListener> listeners = handlers.getRegisteredListeners();
        for (RegisteredListener registration : listeners) {
            try {
                registration.callEvent(event);
            } catch (Throwable ex) {
                Log.e(TAG, "Could not pass event " + event.getClass().getSimpleName() + " to " + registration.getListener().getClass().getName(), ex);
            }
        }
    }
}

HandlerList is simply a container for the List<RegisteredListener> . HandlerList只是List<RegisteredListener>的容器。

Some event listeners that need to be unregistered after being called and this leads to a ConcurrentModificationException in the loop. 某些事件侦听器在被调用后需要取消注册,这会导致循环中出现ConcurrentModificationException The system is performance critical and I would like to avoid doing List.toArray() or similar copies for each event; 系统性能至关重要,我想避免为每个事件做List.toArray()或类似的副本; there are often chunks of 100 events. 经常有100个事件。 How can I allow the modification of the list from a child listener? 如何允许从子监听器修改列表?

A few comments: 一些评论:

  • you could put your listeners in a CopyOnWriteArrayList which is well suited for that type of operation (it will prevent CME) and removes the need for an explicit lock 你可以将你的监听器放在一个非常适合这种操作类型的CopyOnWriteArrayList中(它将阻止CME),并且不需要显式锁定
  • List.toArray is really fast (copying a list of size 100 should take less than a microsecond) List.toArray非常快(复制100大小的列表应该不到一微秒)
  • You should try not to call alien methods from a synchronized block ( registration.callEvent(event) ) as it could lead to annoying bugs such as deadlocks for example. 您应该尝试不从同步块( registration.callEvent(event) )调用alien方法,因为它可能导致恼人的错误,例如死锁。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM