【发布时间】:2014-10-02 21:20:06
【问题描述】:
我在 Map 中维护可变数量的事件侦听器:
private final Map<String, EventListener> eventListeners = new ConcurrentHashMap<>();
使用地图的类有添加事件监听的方法:
public void addEventListener(final String name, final EventListener listener) {
eventListeners.put(name, listener);
}
每次发生事件时,我都会遍历所有侦听器并触发它们:
eventListeners.forEach((name, listener) -> {
listener.handle(event);
});
环境是单线程的,有趣的部分是事件监听器实现可能会在它们被触发时插入另一个事件监听器。
使用“普通”HashMap,这显然会导致ConcurrentModificationException,这就是我使用ConcurrentHashMap的原因。
我看到的情况是,由另一个事件侦听器插入的事件侦听器可能会被同一个事件触发,因为它是在迭代期间插入的,我认为这是ConcurrentHashMap 的预期行为。
但是,我不希望这种情况发生,所以我想推迟事件侦听器的任何插入,直到对所有侦听器的迭代完成。
所以我引入了一个Thread,它在使用CountDownLatch 插入侦听器之前等待迭代完成:
public void addEventListener(final String name, final EventListener listener) {
new Thread(() -> {
try {
latch.await();
} catch (InterruptedException e) {}
eventListeners.put(name, listener);
}).start();
}
以及对所有侦听器的迭代:
latch = new CountDownLatch(1);
eventListeners.forEach((name, listener) -> {
listener.handle(event);
});
latch.countDown();
它按预期工作,但我想知道这是否是一个好的解决方案,是否有更优雅的方法来实现我需要的。
【问题讨论】:
标签: java multithreading events collections