Memra

Concurrent collections & CompletableFuture

Thread-safe collections from java.util.concurrent and chaining async operations.

Don't use plain HashMap across threads

A HashMap is not thread-safe. Concurrent puts from two threads can corrupt its internal structure — potentially causing an infinite loop (the classic Java 6 bug) or data loss. The java.util.concurrent package provides drop-in replacements:

Map<String, Integer> map  = new ConcurrentHashMap<>();
List<String>         list  = new CopyOnWriteArrayList<>();

ConcurrentHashMap segments its buckets so reads are lock-free and writes lock only the relevant segment — much faster than Collections.synchronizedMap.

CopyOnWriteArrayList copies the entire array on each write — great for lists that are read often and written rarely (e.g. event listener registries).

BlockingQueue adds blocking put/take operations — ideal for producer-consumer pipelines:

BlockingQueue<String> queue = new LinkedBlockingQueue<>();
// producer thread:
queue.put("item");   // blocks if the queue is full
// consumer thread:
String item = queue.take();  // blocks if the queue is empty

CompletableFuture enables chained asynchronous operations:

CompletableFuture.supplyAsync(() -> fetchUser(userId))   // runs on common pool
    .thenApply(user -> user.getName())                    // transform the result
    .thenCompose(name -> sendEmail(name))                 // chain another async op
    .exceptionally(ex -> { log(ex); return null; });      // error handler

- supplyAsync — starts the pipeline on the ForkJoinPool common pool. - thenApply — synchronous transform (like Stream.map). - thenCompose — chains another CompletableFuture (like Stream.flatMap). - thenAccept — terminal consumer that returns CompletableFuture<Void>.

NORMAL ~/memra/learn/java-from-zero/concurrent-collections-completablefuture utf-8 LF