简体   繁体   English

在事件总线中避免ConcurrentModificationException

[英]Avoiding ConcurrentModificationException in Event Bus

I have a EventBus system which clients can at will join / leave. 我有一个EventBus系统,客户可以随意加入/离开。

The EventBus is using HashSet to keep track of clients, and when a message is broadcasted, it's delivered to all registered clients. EventBus使用HashSet来跟踪客户端,并在广播消息时将其传递给所有注册的客户端。

// clients - HashSet of clients.
// message - event object to be delivered

for (Object client : clients) {
    sendTo(client, message);    
}

I know this is inefficient, but I don't know how to improve it. 我知道这是低效的,但我不知道如何改善它。

The problem is that the clients can react to some events by disconnecting from the bus. 问题在于客户端可以通过断开与总线的连接来对某些事件做出反应。 Let's take it as a fact, it must be possible. 让我们将其视为事实,这一定是可能的。

They call this method: 他们称这种方法:

public void unsubscribe(Object client)
{
    clients.remove(client);
}

And then, of course, I get an error: 然后,当然,我得到一个错误:

[!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!] 

Not cool, right? 不酷吧?

Any idea to fix this? 有解决这个问题的主意吗?

You can use a LinkedList for this. 您可以为此使用LinkedList

With a LinkedList, you can use its iterator to loop through it, and use that same iterator to remove the object from the LinkedList. 使用LinkedList,您可以使用其迭代器在其中循环,并使用相同的迭代器从LinkedList中删除对象。

Example: 例:

List<Client> clients = new LinkedList<>();
Iterator it = clients.iterator();

while (it.hasNext())
{
  Client client = (Client) it.next();
  sendTo(client, message);
  it.remove();
}

The easiest way is mark clients which should be removed and then remove them in "safe" place. 最简单的方法是标记应删除的客户端,然后在“安全”位置将其删除。

public void unsubscribe(Object client)
{
    clientsToRemove.add(client);
}

And in code something like this : 并在代码中是这样的:

for (Object client : clients) {
    sendTo(client, message);    
}
client.removeAll(clientsToRemove);

If you use an Iterator, you can modify a collection during iteration. 如果使用Iterator,则可以在迭代期间修改集合。 For more information, see The Collection Interface tutorial: http://docs.oracle.com/javase/tutorial/collections/interfaces/collection.html 有关更多信息,请参见“收集接口”教程: http : //docs.oracle.com/javase/tutorial/collections/interfaces/collection.html

I've solved it by using CopyOnWriteArraySet instead of HashSet . 我已经通过使用CopyOnWriteArraySet而不是HashSet解决了它。

Thanks for the suggestions anyway, it can help someone else. 无论如何,感谢您的建议,它可以帮助其他人。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 避免 TreeMap ConcurrentModificationException? - Avoiding TreeMap ConcurrentModificationException? 序列化为 Json 时避免 ConcurrentModificationException? - Avoiding ConcurrentModificationException when serializing to Json? 在dijkstra的算法中避免ConcurrentModificationException - Avoiding ConcurrentModificationException in dijkstra's algorithm 通过制作浅表副本来避免List上的ConcurrentModificationException - Avoiding ConcurrentModificationException on List by making a shallow copy 如何在避免ConcurrentModificationException的同时迭代HashMap - How to iterate over a HashMap while avoiding ConcurrentModificationException 修改多个地图时避免ConcurrentModificationException - Avoiding ConcurrentModificationException while modifying multiple Maps 在Java中使用嵌套的for循环时避免ConcurrentModificationException - Avoiding ConcurrentModificationException when using nested for-loops in Java 遍历集合,在循环中删除对象时避免 ConcurrentModificationException - Iterating through a Collection, avoiding ConcurrentModificationException when removing objects in a loop 过滤Java中的列表,同时避免o(n)复杂性导致的ConcurrentModificationException - Filtering a list in Java while avoiding ConcurrentModificationException in o(n) complexity iOS中的事件总线等价物 - Event Bus equivalent in iOS
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM