Concurrent collections
Share collections between threads without locks and without lost updates.
Open this lesson in the learning hubKey points
- Plain
HashMapandArrayListare not thread-safe. Concurrent writes lose updates or corrupt state. ConcurrentHashMaplocks only the bucket being written, so reads never block.mergeis atomic per key.- It forbids
nullkeys and values, becausenullcould not tell "absent" from "mapped to null" in a racy read. CopyOnWriteArrayListcopies the whole array on every write. Perfect for listener lists: many reads, almost no writes.- A
BlockingQueuehands work from producers to consumers.putandtakeblock until they can proceed. - Their iterators are weakly consistent: they never throw
ConcurrentModificationException, but may miss very recent changes.
Example
import java.util.*;
import java.util.concurrent.*;
public class Main {
public static void main(String[] args) throws Exception {
Map<String, Integer> safe = new ConcurrentHashMap<>();
Map<String, Integer> unsafe = new HashMap<>();
List<String> log = new CopyOnWriteArrayList<>();
ExecutorService pool = Executors.newFixedThreadPool(4);
for (int t = 0; t < 4; t++) {
pool.submit(() -> {
for (int i = 0; i < 5_000; i++) {
safe.merge("hits", 1, Integer::sum);
unsafe.merge("hits", 1, Integer::sum);
}
log.add(Thread.currentThread().getName());
});
}
pool.shutdown();
pool.awaitTermination(5, TimeUnit.SECONDS);
System.out.println("ConcurrentHashMap : " + safe.get("hits") + " (always 20000)");
System.out.println("plain HashMap : " + unsafe.get("hits") + " (usually wrong)");
System.out.println("CopyOnWriteList : " + log.size() + " entries, no exception");
BlockingQueue<String> jobs = new LinkedBlockingQueue<>();
jobs.put("build");
jobs.put("test");
System.out.println("take() : " + jobs.take());
System.out.println("poll(50ms) : " + jobs.poll(50, TimeUnit.MILLISECONDS));
System.out.println("poll(50ms) empty : " + jobs.poll(50, TimeUnit.MILLISECONDS));
}
}
The moment two threads touch a collection, switch to java.util.concurrent.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Collections course, and every lesson in it is listed on the Collections contents page.