0

问题的一些背景:我有一个班级负责通知各种客户有关服务的变化。因此,该类具有多个侦听器的 HashMap,并在需要时通过迭代这些 HashMap 来调用它们的方法(它还具有从这些 HashMap 添加/删除侦听器的方法)。问题是,我经常需要在迭代某些侦听器时删除它们……而且我需要能够从循环外部调用 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();
    }}

以及我想调用 remove(...) 的方式(以及如何失败):

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

有什么技巧可以做到这一点吗?

4

2 回答 2

2

你试过 ConcurrentHashMap 吗?

http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentHashMap.html

于 2013-06-12T18:37:41.223 回答
1

您的问题是使用ConcurrentHashMap. 只需将您的地图定义替换为ConcurrentHashMap

Map<Listener, Boolean> listeners = new ConcurrentHashMap<Listener, Boolean>();
于 2013-06-12T18:42:50.033 回答