首页 > 解决方案 > 与 Guava HashBiMap 和 synchronizedBiMap 同步

问题描述

在多线程情况下,我从 Guava BiMap 的 putIfAbsent 方法中得到一个异常。我应该如何正确保护它免受线程问题的影响?

我这样创建地图:

BiMap<Integer, java.net.URI> cache = com.google.common.collect.Maps.synchronizedBiMap(HashBiMap.create());

然后,我修改地图的唯一时间是 bycache.clear();cache.putIfAbsent(a,b)

我偶尔会看到这个堆栈跟踪:

java.lang.IllegalArgumentException: value already present: http://example.com
    at com.google.common.collect.HashBiMap.put(HashBiMap.java:279)
    at com.google.common.collect.HashBiMap.put(HashBiMap.java:260)
    at java.util.Map.putIfAbsent(Map.java:744)
    at com.google.common.collect.Synchronized$SynchronizedMap.putIfAbsent(Synchronized.java:1120)

这是 HashBiMap 或 synchronizedBiMap 中的错误吗?还是我需要为线程安全做额外的工作?

使用guava-25.0-jreJava(TM) SE Runtime Environment 1.8.0_152-b16

标签: javaguava

解决方案


因为 aBiMap提供了从值到键的映射,以及Map从键到值的通常映射,所以每个值只能与单个键配对。尝试将一个值与多个唯一键相关联将导致IllegalArgumentException您看到的结果。

听起来您的问题与线程无关,而是与数据有关。

例如,这将引发类似的异常。问题是存在带有两个单独键“Foo”和“Baz”的值“Bar”:

    public static void main(String[] args) {
        BiMap<String, String> m = HashBiMap.create();
        m.put("Foo", "Bar");
        m.put("Baz", "Bar"); // Throws IllegalArgumentException "value already present"
    }

推荐阅读