为了账号安全,请及时绑定邮箱和手机立即绑定

可以在没有迭代的情况下获取、放置和删除 HashMap 中的 elemetn

可以在没有迭代的情况下获取、放置和删除 HashMap 中的 elemetn

江户川乱折腾 2021-09-03 16:19:23
我有一个静态 hashMap,与多个线程共享。我根本没有迭代地图,而只是使用get, put, remove。安全ConcurrentModificationException吗?该方法看起来像这样private static Map<Long, Integer> TRACKER = new HashMap<Long,Integer>();public static void track(Long tid, boolean b) {        if (b) {            if (TRACKER.containsKey(tid)) {                TRACKER.put(tid, TRACKER.get(tid) + 1);            } else {                TRACKER.put(tid, 1);            }        } else {            Integer n = TRACKER.get(tid);            if (n != null) {                n = n -1;                if (n == 0) {                    TRACKER.remove(tid);                } else {                    TRACKER.put(tid, n);                }            }        }    }
查看完整描述

2 回答

?
噜噜哒

TA贡献1784条经验 获得超7个赞

安全ConcurrentModificationException吗?

它是安全的ConcurrentModificationException。该异常仅由使用传统迭代器或拆分器迭代(在某种意义上)地图或其视图之一的方法抛出。

但是,由于HashMap它不是线程安全的类,如果在没有适当外部外部同步的情况下从多个线程使用它,可能会发生不好的事情。这些包括(按不良程度增加的顺序)

  1. size()报告错误值的方法。

  2. 条目神秘地暂时或永久消失。

  3. 可能的 NPE 和其他未经检查的异常。

  4. 由于多个线程在哈希链中创建循环的不幸操作序列,可能导致无限循环。

您的示例代码不安全……但您不会得到“快速失败” ConcurrentModificationException。相反,您可能会在难以重现的“随机”时间出现莫名其妙的错误。


查看完整回答
反对 回复 2021-09-03
?
萧十郎

TA贡献1815条经验 获得超13个赞

如果多个线程在 a上执行getput&remove操作HashMap,没有适当的同步,一些不好的事情,比如 size() 报告丢失/丢失的条目,意外的 NPE ......甚至可能会发生无限循环。

HashMap文档说 -

请注意,此实现不是同步的。如果多个线程并发访问一个散列映射,并且至少有一个线程在结构上修改了映射,则必须在外部进行同步。(结构修改是添加或删除一个或多个映射的任何操作;仅更改与实例已包含的键关联的值不是结构修改。)...

谢谢斯蒂芬。


查看完整回答
反对 回复 2021-09-03
  • 2 回答
  • 0 关注
  • 161 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信