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
- ConcurrentHashMap构造函数参数?
- ConcurrentHashMap是否可能“死锁”?
- 需要简单解释“锁定条带化”如何与ConcurrentHashMap一起使用
- 使用ConcurrentHashMap消除了数据可见性问题?
- “在Java 8中构建时,未定义的引用:.. ConcurrentHashMap.keySet()”
- ConcurrentHashMap jdk 8使用TreeNodes而不是List ..为什么?
- 同步局部变量
- ThreadLocal HashMap vs ConcurrentHashMap用于线程安全的未绑定缓存
- 在ConcurrentHashMap中修改值的首选方法是什么?