我总是很犹豫是否要把我的锁公开,公开。我总是尝试将锁限制在我的实现范围内。我相信,不这样做就会导致僵局。
我有以下课程:
class SomeClass {
protected ArrayList<Listener> mListeners = new ArrayList<Listener>();
protected void addListener(Listener listener) {
synchronized (mListeners) {
mListeners.add(listener);
}
}
protected void removeListener(Listener listener) {
synchronized (mListeners) {
mListeners.remove(listener);
}
}
...
}
当 SomeClass 想要通知他的听众时,你会这样做:
synchronized (mListeners) {
for (Listener l : mListeners) {
l.event();
}
}
or
Listener[] listeners = null;
synchronized (mListeners) {
listeners = mListeners.toArray();
}
for (Listener l : listeners) {
l.event();
}
我会选择第二个选项。缺点是监听器可以获取事件,即使它们已经未注册。好处是,等待侦听器回调的线程在想要取消注册侦听器时不会陷入死锁。我相信好处比坏处更重要,这很容易记录下来。
所以这里的问题基本上是:你会暴露你的锁吗?
我的问题不是你是否会选择一个普通的 ArrayList、一个 LinkedList、一个 ConcurrentLinkedQueue、一个 CopyOnWriteArrayList、一个...!这是您是否介意侦听器在未注册时是否可以收到通知。问题在于你是否愿意把锁打开。这是为了避免僵局,或者不是。
请分享您的想法。谢谢!
Use a CopyOnWriteArrayList
对于您的侦听器数组。
这对于不经常更改的监听器数组来说是完美的。当您迭代它们时,您正在迭代底层数组。与一个CopyOnWriteArrayList
,该数组每次修改时都会被复制。因此,在迭代时无需与其同步,因为每个底层数组都保证是静态的,即使在其在内部使用之后也是如此。CopyOnWriteArrayList
.
Since CopyOnWriteArrayList
也是线程安全的,不需要同步add和remove操作。
宣言:
private final CopyOnWriteArrayList<Listener> listeners;
事件触发:
for (Listener l: this.listeners) {
l.event();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)