Java ConcurrentHashMap不是线程安全的..是吗?

之前我正在使用HashMap

public Map clients = new HashMap(); 

现在我已经切换到ConcurrentHashMap以避免同步块,现在我遇到了问题,我的服务器每秒都有大量加载200-400个并发客户端,预计会随着时间的推移而增长。

现在看起来像这样

 public ConcurrentHashMap clients = new ConcurrentHashMap(); 

我的服务器设计就像这样。 我有一个工作线程来处理大量的数据包。 每个数据包都使用packetHandler子程序(不是线程的一部分)进行检查,几乎任何客户端都可以在任何时候调用它,它几乎就像静态但不是。

我的整个服务器大多是单线程的,除了数据包处理部分。

无论如何,当有人使用命令时,如在线计算所有客户并从中获取一些信息。

客户端也可能会在计数正在进行时断开连接并从ConcurrentHashMap中删除(这会导致我的问题)。

另外我想在这里添加一些代码。

  int txtGirls=0; int vidGirls=0; int txtBoys=0; int vidBoys=0; Iterator i = clients.values().iterator(); while (i.hasNext()) { UserProfile person = (UserProfile)i.next(); if(person != null) { if(person.getChatType()) { if(person.getGender().equals("m")) vidBoys++; else //<-- crash occurs here. vidGirls++; } else if(!person.getChatType()) { if(person.getGender().equals("m")) txtBoys++; else txtGirls++; } } } 

我的意思是我当然要通过在Iterator中添加一个try-catch Exception来跳过这些空客户端来修复它。

但我不明白,如果检查上面是否(人!= null)不应该嵌套的代码自动工作..

如果它不意味着它在迭代时被删除了,这应该是不可能的,因为它是线程安全的wtf?

我该怎么办? 或者是try-catch Exception最好的方法?

这是例外

 java.lang.NullPointerException at Server.processPackets(Server.java:398) at PacketWorker.run(PacketWorker.java:43) at java.lang.Thread.run(Thread.java:636) 

processPackets包含上面的代码。 并且注释表示行数#

谢谢你的启发。

您需要读取ConcurrentHashMap.values()方法的javadoc,特别注意values()集合的迭代器如何工作的描述:

“视图的迭代器是一个”弱一致“的迭代器,它永远不会抛出ConcurrentModificationException,并保证遍历构造迭代器时存在的元素,并且可能(但不保证)反映构造之后的任何修改。

迭代器不会为您提供值集合状态的一致快照,但它是线程安全的 ,并且明确指定了预期的行为范围。

如果您希望Map实现为您提供映射中值(或键或条目)的一致快照,并允许您同时进行修改,则可能需要创建自定义Map包装类(复制集合)primefaces地)…或完整的自定义Map实现。 对于您的用例,两者都可能比ConcurrentHashMap慢很多。

java.util.concurrent.ConcurrentHashMap不允许空值。 因此,代码中的null check(person!= null)是不必要的。

如果要在迭代时拒绝修改Map,则必须在上面的代码和所有修改操作代码中使用同步块。

我没有看到你的代码有什么问题。 因为崩溃实际上不太可能发生在else ,所以getGender()方法很可能返回null

您可能会发现在迭代它时不能修改地图。 如果是这种情况,您可能希望在单独的集合中获取值和键并迭代它,因为它将是不可变的。

它不是完美的,但另一个选择是扩展ConcurrentHashMap ,当添加或删除某些内容时,您更新这四个变量,因此您不必每次都遍历整个列表,因为这似乎是浪费cpu周期。

以下是一些可能有用的链接:

这个讲述了一个事实,即改进的并发性是因为放松了一些承诺。 http://www.ibm.com/developerworks/java/library/j-jtp07233.html

内存一致性属性解释: http : //download-llnw.oracle.com/javase/6/docs/api/java/util/concurrent/package-summary.html#MemoryVisibility