Memra

Concurrent collections & CompletableFuture

◈ 4 cards

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>.
UserString namesupplyAsyncfetchUser(userId)thenApplyuser.getName()thenComposesendEmail(name)
thenApply transforms the value in place; thenCompose chains another CompletableFuture — the same distinction as map versus flatMap. .exceptionally(...) at the end of the chain catches a failure from any stage.
NORMAL ~/memra/learn/java-from-zero/concurrent-collections-completablefuture utf-8 LF