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

Java Concurrent Collections

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;
public class Main {
	public static void main(String[] args) throws InterruptedException {
		ConcurrentHashMap<Integer, Integer> map = new ConcurrentHashMap<>();
		Runnable task = () -> { for (int i = 0; i < 100; i++) map.put(i, i); };
		Thread t1 = new Thread(task), t2 = new Thread(task);
		t1.start(); t2.start();
		t1.join(); t2.join();
		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
	}
}

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.