ConcurrentHashMap · Topic 3 of 6
putIfAbsent and computeIfAbsent
Definition​
putIfAbsent stores a value only if the key is missing. computeIfAbsent also builds the value only when it is missing, and does it once even if many threads ask at the same time. That makes it a simple, safe cache.
Example code​
A cache that loads each key only once
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
class Demo {
static final ConcurrentHashMap<String, String> cache = new ConcurrentHashMap<>();
static final AtomicInteger loads = new AtomicInteger();
static String load(String key) {
loads.incrementAndGet(); // pretend this is a slow database call
return "value-of-" + key;
}
public static void main(String[] args) throws Exception {
ExecutorService pool = Executors.newFixedThreadPool(8);
for (int i = 0; i < 8; i++) {
pool.submit(() -> cache.computeIfAbsent("user:42", Demo::load)); // 8 threads, same key
}
pool.shutdown();
pool.awaitTermination(10, TimeUnit.SECONDS);
System.out.println(cache.get("user:42"));
System.out.println("loaded " + loads.get() + " time(s)"); // once, not eight times
System.out.println(cache.putIfAbsent("user:42", "other")); // returns the existing value
}
}
// Output:
// value-of-user:42
// loaded 1 time(s)
// value-of-user:42
Finished this page? Track your progress (saved only in your browser).