javaadvanced

Concurrent Collections — Thread-Safe Maps

Use ConcurrentHashMap, CopyOnWriteArrayList, and BlockingQueue for thread-safe data structures.

java
import java.util.concurrent.*;
import java.util.*;

public class ConcurrentCollections {
    // Thread-safe cache with ConcurrentHashMap
    static final ConcurrentHashMap<String, String> cache = new ConcurrentHashMap<>();

    static String getOrCompute(String key) {
        return cache.computeIfAbsent(key, k -> {
            System.out.println("Computing: " + k);
            return k.toUpperCase(); // expensive computation
        });
    }

    // Producer-Consumer with BlockingQueue
    static void producerConsumer() throws InterruptedException {
        BlockingQueue<String> queue = new LinkedBlockingQueue<>(10);

        // Producer
        Thread producer = Thread.ofVirtual().start(() -> {
            for (int i = 0; i < 20; i++) {
                try {
                    queue.put("Item-" + i); // blocks if full
                    System.out.println("Produced: Item-" + i);
                } catch (InterruptedException e) { break; }
            }
        });

        // Consumer
        Thread consumer = Thread.ofVirtual().start(() -> {
            while (true) {
                try {
                    String item = queue.poll(2, TimeUnit.SECONDS);
                    if (item == null) break;
                    System.out.println("Consumed: " + item);
                } catch (InterruptedException e) { break; }
            }
        });

        producer.join();
        consumer.join();
    }

    // Atomic operations
    static void atomicOps() {
        // Atomic merge — thread-safe counter
        ConcurrentHashMap<String, Long> counters = new ConcurrentHashMap<>();
        counters.merge("page-views", 1L, Long::sum);
        counters.merge("page-views", 1L, Long::sum);
        System.out.println(counters); // {page-views=2}

        // CopyOnWriteArrayList — safe for iteration-heavy workloads
        CopyOnWriteArrayList<String> listeners = new CopyOnWriteArrayList<>();
        listeners.add("listener1");
        listeners.add("listener2");
        // Safe to iterate while others modify
        for (String l : listeners) {
            System.out.println("Notifying: " + l);
        }
    }

    public static void main(String[] args) throws Exception {
        getOrCompute("hello");
        getOrCompute("hello"); // cached, no recompute
        producerConsumer();
        atomicOps();
    }
}

Use Cases

  • Thread-safe caching in multi-threaded applications
  • Producer-consumer queue processing
  • Lock-free concurrent counters and accumulators

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.