Is there java.util.concurrent equivalent for WeakHashMap?
Asked Answered
S

7

59

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

Spiritism answered 13/2, 2010 at 0:16 Comment(1)
The important benefit of highly concurrent data structures such as ConcurrentHashMap is that it can (through a variety of techniques) remain thread-safe under heavy load without (much) blocking. It is important to realize that if your class is not under heavy load, your performance with ConcurrentHashMap could be worse than with HashMap. If your environment is expected to be largely free of contention that you can use external synchronization and you'll be just fine.Wnw
M
43

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.

Madalynmadam answered 13/2, 2010 at 0:38 Comment(1)
Updated link to Guava: github.com/google/guava and updated link for CacheBuilder: google.github.io/guava/releases/18.0/api/docs/com/google/common/…Pinguid
I
23

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."

Iterate answered 13/2, 2010 at 0:34 Comment(2)
@rogerdpack: but you could always compose a WeakHashMap into a roll-your-own ThreadSafeWeakHashMap and, using a monitor lock, write your own putIfAbsent(...) pretty easily. Agreed that this would be suboptimal under heavy loads but not everything is heavily loaded.Wnw
@rogerdpack it does now, Java 8 ftwSemicolon
R
3

If you happen to have the Spring Framework in your classpath already, then one option is ConcurrentReferenceHashMap:

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/util/ConcurrentReferenceHashMap.html

You can choose between using weak or soft references (for both the keys and values).

Ranger answered 13/8, 2021 at 13:9 Comment(0)
W
2

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));
Wanting answered 13/10, 2017 at 16:4 Comment(0)
F
1

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!)

Fatalism answered 17/2, 2017 at 10:23 Comment(2)
Correct. The JVM is always multi-threaded. There are GC threads, finalizer threads, and others. If WeakHashMap didn't work in an explicitly multithreaded Java program, it's hard to see how it could work in a single-threaded one either.Motorize
Huh? You are missing the whole question. He is asking for a weak version of ConcurrentHashMap (which uses a different algorithm than WeakHashMap).Sidle
M
-1

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.

Mande answered 5/3, 2012 at 19:18 Comment(0)
D
-1

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.

Dc answered 4/4, 2018 at 9:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.