Skip to main content

Concurrent Collections

Concurrent collections are specialized data structures in Java designed to handle multi-threaded environments safely. Unlike traditional collections (e.g., ArrayList, HashMap), concurrent collections ensure thread safety without requiring explicit synchronization.

In Java, the java.util.concurrent package provides several concurrent collection classes, such as ConcurrentHashMap, CopyOnWriteArrayList, and BlockingQueue.


Why Use Concurrent Collections?​

  • Thread Safety: Concurrent collections handle synchronization internally, reducing the risk of race conditions.
  • Performance: They are optimized for high concurrency, offering better performance than synchronized collections.
  • Ease of Use: Simplifies thread-safe programming by eliminating the need for manual synchronization.

Common Concurrent Collections​

  1. ConcurrentHashMap:

    • A thread-safe implementation of HashMap.
    • Allows concurrent read and write operations without locking the entire map.
  2. CopyOnWriteArrayList:

    • A thread-safe variant of ArrayList.
    • Creates a new copy of the list whenever it is modified, ensuring safe iteration.
  3. BlockingQueue:

    • A thread-safe queue that supports operations that wait for the queue to become non-empty when retrieving elements or wait for space to become available when adding elements.
    • Common implementations: ArrayBlockingQueue, LinkedBlockingQueue.

Example: Using ConcurrentHashMap​

Below is an example of using ConcurrentHashMap to perform thread-safe operations in a multi-threaded environment.

import java.util.concurrent.ConcurrentHashMap;

public class ConcurrentHashMapExample {
public static void main(String[] args) {
// Create a ConcurrentHashMap
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

// Add key-value pairs
map.put("Alice", 25);
map.put("Bob", 30);

// Simulate concurrent updates
Runnable task = () -> {
map.compute("Alice", (key, value) -> value == null ? 1 : value + 1);
System.out.println(Thread.currentThread().getName() + " updated Alice's value to " + map.get("Alice"));
};

// Create multiple threads to update the map concurrently
Thread thread1 = new Thread(task);
Thread thread2 = new Thread(task);

thread1.start();
thread2.start();

try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
System.out.println("Thread interrupted.");
}

System.out.println("Final Map: " + map);
}
}

Output:

Thread-0 updated Alice's value to 26
Thread-1 updated Alice's value to 27
Final Map: {Alice=27, Bob=30}

Explanation:

  • The ConcurrentHashMap allows multiple threads to update the map concurrently without causing race conditions.
  • The compute() method safely updates the value associated with a key.

Key Takeaways​

  • Use concurrent collections like ConcurrentHashMap, CopyOnWriteArrayList, and BlockingQueue for thread-safe operations.
  • Concurrent collections eliminate the need for explicit synchronization, improving performance and readability.
  • Always choose the appropriate concurrent collection based on your use case (e.g., ConcurrentHashMap for maps, BlockingQueue for producer-consumer scenarios).