【发布时间】:2020-05-06 00:56:42
【问题描述】:
我们在我们的应用程序中使用了 HashBiMap,我们是这样创建的
HashBiMap<String, String> map = HashBiMap.create();
我们有 guava-26.0-jre 版本的 guava。
最近注意到我们的应用程序挂起并且无法处理任何其他请求。得到一个线程转储并注意到类似的事情
Thread.State: RUNNABLE
native=false, suspended=false, blockCount=1, waitCount=4, cpu=9h, 12m, 45s, 434ms, user=9h, 10m, 59s, 990ms
com.google.common.collect.HashBiMap.seekByKey(HashBiMap.java:223)
com.google.common.collect.HashBiMap.get(HashBiMap.java:254)
Thread.State: RUNNABLE
native=false, suspended=false, blockCount=1, waitCount=6, cpu=9h, 11m, 49s, 453ms, user=9h, 10m, 3s, 760ms
com.google.common.collect.HashBiMap.seekByKey(HashBiMap.java:223)
com.google.common.collect.HashBiMap.get(HashBiMap.java:254)
Thread.State: RUNNABLE
native=false, suspended=false, blockCount=274, waitCount=6615, cpu=22h, 31m, 29s, 966ms, user=22h, 27m, 30s, 540ms
com.google.common.collect.HashBiMap.seekByKey(HashBiMap.java:223)
com.google.common.collect.HashBiMap.get(HashBiMap.java:254)
Thread.State: RUNNABLE
native=false, suspended=false, blockCount=91, waitCount=2443, cpu=22h, 29m, 51s, 541ms, user=22h, 25m, 54s, 140ms
com.google.common.collect.HashBiMap.seekByKey(HashBiMap.java:223)
com.google.common.collect.HashBiMap.get(HashBiMap.java:254)
上面还有几个其他线程在调用 get 时被阻塞,但等待时间最长的是 cpu=22h, 31m, 29s, 966ms
Thread.State: RUNNABLE
native=false, suspended=false, blockCount=3, waitCount=32, cpu=5h, 46m, 7s, 733ms, user=5h, 45m, 500ms
com.google.common.collect.HashBiMap.seekByValue(HashBiMap.java:234)
com.google.common.collect.HashBiMap.put(HashBiMap.java:274)
com.google.common.collect.HashBiMap.forcePut(HashBiMap.java:301)
只有一个线程在等待上面的 forcePut。
HashBiMap.get 会进入循环以查找键的值并且永远不会返回,是否有任何理由。
【问题讨论】:
-
当多个线程在没有适当同步的情况下访问一个数据结构时,经常会发生这种情况。
-
如果您的 bimap 确实是从多个线程访问的,请用
Maps#synchronizedBiMap包装它以避免此类问题。