在没有迭代器的情况下同时修改/删除HashMap中的条目

时间:2013-06-12 18:35:55

标签: java hashmap concurrentmodification

问题的一些背景:我有一个班,负责通知各个客户有关服务的变化。因此,该类有几个HashMaps的侦听器,并在需要时通过迭代这些HashMaps来调用它们的方法(它还有从这些HashMaps添加/删除侦听器的方法)。问题是我经常需要在迭代时删除某些侦听器...... 我需要能够从循环外部调用remove(...)方法。 两者都在迭代和删除发生在同一个线程上。类的例子:

class SomeClass {
    Map<Listener, Boolean> listeners = new HashMap<Listener, Boolean>();

    void add(Listener listener) {
        listeners.put(listener, true);
    }

    void remove(Listener listener) {
        listeners.remove(listener);
    }

    void notifyListeners() {
        Iterator<Map.Entry<Listener, Boolean>> it = listeners.entrySet().iterator();
        while (it.hasNext()) {
            it.next().getKey().onDo();
        }
    }

    static interface Listener{
        void onDo();
    }}

我想要调用的方式删除(...)(以及失败的方式):

final SomeClass someClass = new SomeClass();

    Listener a = new Listener(){
        @Override
        public void onDo() {
            someClass.remove(this);
        }
    };

    Listener b = new Listener(){
        @Override
        public void onDo() {
            someClass.remove(this);
        }
    };

    Listener c = new Listener(){
        @Override
        public void onDo() {
            someClass.remove(this);
        }
    };

    someClass.add(a);
    someClass.add(b);
    someClass.add(c);

    someClass.notifyListeners();
    // java.util.ConcurrentModificationException

有没有诀窍呢?

2 个答案:

答案 0 :(得分:2)

答案 1 :(得分:1)

您的问题是使用ConcurrentHashMap的候选人。只需将地图定义替换为ConcurrentHashMap

即可
Map<Listener, Boolean> listeners = new ConcurrentHashMap<Listener, Boolean>();