← Back to Advanced Java Course | Chapter 11: Advanced & Security | Lesson 10 of 19

Java Concurrent Collections

Concurrent collections are lists and maps built to be safely used by many threads at once, like a shared whiteboard with good manners. Regular ones can get mixed up if shared.
Syntax
java
ConcurrentHashMap<KeyType, ValueType> map = new ConcurrentHashMap<>();
map.put(key, value);
CopyOnWriteArrayList<Type> list = new CopyOnWriteArrayList<>();

Why Concurrent Collections?

Concurrent collections, defined in java.util.concurrent, provide high-performance, thread-safe alternatives to wrapping a regular collection with Collections.synchronizedList() or similar. They reduce lock contention by segmenting the underlying data instead of locking the whole structure on every access.

Example: Why Concurrent Collections?

java
import java.util.concurrent.ConcurrentHashMap;
public class Main {
	public static void main(String[] args) {
		ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>(); // segmented, not one big lock
		map.put("a", 1);
		System.out.println(map.get("a"));
	}
}

ConcurrentHashMap

ConcurrentHashMap allows safe concurrent reads and writes from multiple threads. It locks only specific segments (or in modern implementations, individual bins) of the map rather than the entire table, so unrelated threads working on different keys rarely block each other.

Example: ConcurrentHashMap

java
// Import java.util.concurrent.ConcurrentHashMap so it can be used by its short name
import java.util.concurrent.ConcurrentHashMap;
// Define the class Main
public class Main {
	// Program entry point: the JVM starts running here
	public static void main(String[] args) throws InterruptedException {
		// Create a new ConcurrentHashMap object and store it in map
		ConcurrentHashMap<Integer, Integer> map = new ConcurrentHashMap<>();
		Runnable task = () -> { for (int i = 0; i < 100; i++) map.put(i, i); };
		// Create a new Thread object and store it in t1
		Thread t1 = new Thread(task), t2 = new Thread(task);
		// Start the thread; it runs in parallel with this code
		t1.start(); t2.start();
		// Wait for the thread to finish
		t1.join(); t2.join();
		// Print a line to the console
		System.out.println(map.size());
	}
}

CopyOnWriteArrayList

CopyOnWriteArrayList is a thread-safe list that creates an entirely fresh copy of its underlying array on every mutation (add, set, remove). This makes writes relatively expensive, but reads never need any locking at all, which makes it ideal for lists that are read constantly but modified only rarely.

Example: CopyOnWriteArrayList

java
import java.util.concurrent.CopyOnWriteArrayList;
public class Main {
	public static void main(String[] args) {
		CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>(); // copies the array on every write
		list.add("a"); // relatively expensive
		for (String item : list) System.out.println(item); // reads need no locking at all
	}
}

BlockingQueue

BlockingQueue is a thread-safe queue designed for producer-consumer patterns: it automatically blocks the producer thread when the queue is full and blocks the consumer thread when the queue is empty, coordinating the two sides without you writing manual wait/notify logic.

Example: BlockingQueue

java
import java.util.concurrent.*;
public class Main {
	public static void main(String[] args) throws InterruptedException {
		BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(1);
		queue.put(1); // fills the queue
		Thread consumer = new Thread(() -> {
			try { System.out.println("Consumed: " + queue.take()); } catch (InterruptedException e) {}
		});
		consumer.start();
		consumer.join();
	}
}

ConcurrentSkipListMap

ConcurrentSkipListMap is a concurrent, sorted map implementation that maintains its keys in sorted order at all times, providing a scalable, thread-safe alternative to TreeMap for situations where multiple threads need sorted access to shared data.

Example: ConcurrentSkipListMap

java
import java.util.concurrent.ConcurrentSkipListMap;
public class Main {
	public static void main(String[] args) {
		ConcurrentSkipListMap<Integer, String> map = new ConcurrentSkipListMap<>();
		map.put(3, "c"); map.put(1, "a"); map.put(2, "b");
		System.out.println(map); // always sorted, thread-safe
	}
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Writing if (!map.containsKey(k)) map.put(k, v) on a ConcurrentHashMap, which is not atomic; use putIfAbsent or computeIfAbsent.
  2. Putting a null key or value into a ConcurrentHashMap, which throws a NullPointerException.
  3. Using CopyOnWriteArrayList for a list that is written often, since every write copies the whole array.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.