与Guava Hashbimap和同步Bimap同步



我在多线程的情况下从guava bimap的putifabsent方法中获得了例外。我应该如何正确保护它免受螺纹问题的侵害?

我这样创建地图:

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

然后,我唯一修改地图的时间是cache.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还是同步bimap中的错误?还是我需要做额外的工作以进行线程安全?

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

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

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

举例来说,这将引发类似的例外。问题是带有两个单独的键" foo"one_answers" 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"
    }

这与同步无关,但这就是BiMap的工作方式。您可以轻松地复制它:

cache.putIfAbsent(1, URI.create("http://example.com"));
cache.putIfAbsent(2, URI.create("http://stackoverflow.com"));
System.out.println(cache);
// {1=http://example.com, 2=http://stackoverflow.com}
cache.putIfAbsent(3, URI.create("http://example.com"));
// java.lang.IllegalArgumentException: value already present: http://example.com

BiMap"一张保留其值及其键的独特性的地图。" 这意味着您甚至在不同的键下也无法再次放置示例。另请参见Wiki页面描述BiMap

BiMap.put(key, value)如果您尝试将键映射到已经存在的值,则会抛出IllegalArgumentException。如果您想删除具有指定值的任何先前的条目,请改用BiMap.forcePut(key, value)

在您的情况下,您可以使用forcePut,并且在例外不要失败:

cache.forcePut(3, URI.create("http://example.com"));
System.out.println(cache);
// {2=http://stackoverflow.com, 3=http://example.com}

最新更新