问题
Can the following piece of code be rewritten w/o using Collections.synchronizedMap()
yet maintaining correctness at concurrency?
Collections.synchronizedMap(new WeakHashMap<Class, Object>());
i.e. is there something from java.util.concurrent one can use instead? Note that merely replacing with
new ConcurrentHashMap<Class, Object>(new WeakHashMap<Class, Object>()));
obviously won't work
回答1:
Guava's CacheBuilder class allows you to do this easily.
CacheBuilder.newBuilder().weakKeys().build()
Note that this changes key equality semantics to be ==
instead of .equals()
which will not matter in your case of using Class
instances but is a potential pitfall.
回答2:
I don't believe there is. In fact the javadoc suggests using Collections.synchronizedMap()
"Like most collection classes, this class is not synchronized. A synchronized WeakHashMap may be constructed using the Collections.synchronizedMap method."
回答3:
Cafeine is a popular competitor of Guava cache.
- keys automatically wrapped in weak references
- values automatically wrapped in weak or soft references
usage:
LoadingCache<Key, Graph> graphs = Caffeine.newBuilder()
.weakKeys()
.weakValues()
.build(key -> createExpensiveGraph(key));
回答4:
Does wrapping the WeakHashMap in a synchronized map still work correctly for what you want to do, since the garbage collector can modify the weakreferences directly at anytime, bypassing the synchronized map wrapper? I think WeakHashMap only truly works in a single threaded model.
As mentioned above, the documentation for WeakHashMap at https://docs.oracle.com/javase/7/docs/api/java/util/WeakHashMap.html specifically says:
"A synchronized WeakHashMap may be constructed using the Collections.synchronizedMap method"
Which implies to me that this technique must work in tandem with the garbage collector's behavior (unless the documentation is buggy!)
回答5:
If you are using Java 7 and above, this use case is solved in a thread-safe manner with ClassValue
https://docs.oracle.com/javase/7/docs/api/java/lang/ClassValue.html If you require the use of remove
, think carefully about concurrency and read the doc thoroughly.
If you are using Java 6 or below. No, you have to synchronize a WeakHashMap.
回答6:
Does wrapping the WeakHashMap in a synchronized map still work correctly for what you want to do, since the garbage collector can modify the weakreferences directly at anytime, bypassing the synchronized map wrapper? I think WeakHashMap only truly works in a single threaded model.
来源:https://stackoverflow.com/questions/2255950/is-there-java-util-concurrent-equivalent-for-weakhashmap