我有一个EventBus
系统,客户可以随时加入/离开。
EventBus
正在使用HashSet
跟踪客户端,并在广播消息时将其发送给所有已注册的客户。
// clients - HashSet of clients.
// message - event object to be delivered
for (Object client : clients) {
sendTo(client, message);
}
我知道这是低效的,但我不知道如何改进它。
问题是客户端可以通过断开与总线的连接来对某些事件做出反应。让我们把它当作一个事实,它必须是可能的。
他们称这种方法为:
public void unsubscribe(Object client)
{
clients.remove(client);
}
然后,当然,我收到一个错误:
[!E!] java.util.ConcurrentModificationException
[!E!] at java.util.LinkedHashMap$LinkedHashIterator.nextEntry(LinkedHashMap.java:390)
[!E!] at java.util.LinkedHashMap$KeyIterator.next(LinkedHashMap.java:401)
[!E!] at mightypork.utils.control.bus.EventChannel.doBroadcast(EventChannel.java:56)
[!E!] at mightypork.utils.control.bus.EventChannel.broadcast(EventChannel.java:48)
[!E!] at mightypork.utils.control.bus.EventBus.broadcast(EventBus.java:82)
[!E!] at mightypork.rogue.App.shutdown(App.java:133)
[!E!] at mightypork.rogue.App.start(App.java:87)
[!E!] at mightypork.rogue.App.main(App.java:72)
[!E!]
不酷,对吧?
有什么想法解决这个问题吗?
答案 0 :(得分:1)
您可以使用LinkedList。
使用LinkedList,您可以使用其迭代器循环遍历它,并使用相同的迭代器从LinkedList中删除该对象。
示例:
List<Client> clients = new LinkedList<>();
Iterator it = clients.iterator();
while (it.hasNext())
{
Client client = (Client) it.next();
sendTo(client, message);
it.remove();
}
答案 1 :(得分:0)
最简单的方法是标记应删除的客户端,然后在&#34; safe&#34;中删除它们。的地方。
public void unsubscribe(Object client)
{
clientsToRemove.add(client);
}
在代码中这样:
for (Object client : clients) {
sendTo(client, message);
}
client.removeAll(clientsToRemove);
答案 2 :(得分:0)
如果使用Iterator,则可以在迭代期间修改集合。有关更多信息,请参阅集合界面教程:http://docs.oracle.com/javase/tutorial/collections/interfaces/collection.html
答案 3 :(得分:0)
我已使用CopyOnWriteArraySet
代替HashSet
解决了这个问题。
无论如何,感谢您的建议,它可以帮助其他人。