Detailed Explanation of J.U.C Concurrency Utility Classes in Java

Detailed Explanation of J.U.C Concurrency Utility Classes in Java

I. Overview of J.U.C
J.U.C (java.util.concurrent) is a concurrency programming toolkit provided by Java, containing three major categories of components to solve concurrency problems:

  1. Atomic Classes - Thread-safe atomic operation classes
  2. Lock Mechanisms - More flexible locks than synchronized
  3. Concurrent Collections - Thread-safe collection containers
  4. Thread Pools (Executor) - Thread management and scheduling
  5. Synchronization Utilities - Tool classes for controlling thread execution

II. CountDownLatch

  1. Core Function: Allows one or more threads to wait for other threads to complete operations

  2. Implementation Principle:

    • Internally maintains a counter, initialized with the number of threads to wait for
    • Each thread calls countDown() upon completion, decrementing the counter by 1
    • When the counter reaches 0, waiting threads are awakened
  3. Code Example:

public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(3); // Initial counter set to 3
        
        for (int i = 1; i <= 3; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + " Task completed");
                latch.countDown(); // Counter decrement
            }, "Thread" + i).start();
        }
        
        latch.await(); // Main thread waits until counter reaches 0
        System.out.println("All threads completed tasks, main thread continues execution");
    }
}

III. CyclicBarrier

  1. Core Function: Allows a group of threads to wait for each other, proceeding only after reaching a common barrier point

  2. Differences from CountDownLatch:

    • CountDownLatch is single-use, CyclicBarrier is reusable
    • CountDownLatch involves main thread waiting, CyclicBarrier involves mutual waiting among threads
  3. Code Example:

public class CyclicBarrierDemo {
    public static void main(String[] args) {
        CyclicBarrier barrier = new CyclicBarrier(3, () -> {
            System.out.println("All threads reached barrier, executing barrier action");
        });
        
        for (int i = 1; i <= 3; i++) {
            new Thread(() -> {
                try {
                    System.out.println(Thread.currentThread().getName() + " Reached barrier");
                    barrier.await(); // Wait for other threads
                    System.out.println(Thread.currentThread().getName() + " Continuing execution");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }, "Thread" + i).start();
        }
    }
}

IV. Semaphore

  1. Core Function: Controls the number of threads that can simultaneously access a specific resource

  2. Two Modes:

    • Fair mode: Permits acquired in order of request
    • Non-fair mode: Permits acquired preemptively
  3. Code Example:

public class SemaphoreDemo {
    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(3); // Allows 3 concurrent thread accesses
        
        for (int i = 1; i <= 6; i++) {
            new Thread(() -> {
                try {
                    semaphore.acquire(); // Acquire permit
                    System.out.println(Thread.currentThread().getName() + " Acquired resource");
                    Thread.sleep(2000); // Simulate resource usage
                    System.out.println(Thread.currentThread().getName() + " Released resource");
                    semaphore.release(); // Release permit
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }, "Thread" + i).start();
        }
    }
}

V. Exchanger

  1. Core Function: Used for data exchange between two threads

  2. Execution Flow:

    • Thread A blocks after executing exchange(), waiting for Thread B
    • Thread B executes exchange(), both threads exchange data and continue execution
  3. Code Example:

public class ExchangerDemo {
    public static void main(String[] args) {
        Exchanger<String> exchanger = new Exchanger<>();
        
        new Thread(() -> {
            try {
                String dataA = "Data A";
                System.out.println("Thread A sending: " + dataA);
                String result = exchanger.exchange(dataA);
                System.out.println("Thread A received: " + result);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
        
        new Thread(() -> {
            try {
                String dataB = "Data B";
                System.out.println("Thread B sending: " + dataB);
                String result = exchanger.exchange(dataB);
                System.out.println("Thread B received: " + result);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

VI. Phaser

  1. Core Function: More flexible reusable synchronization barrier supporting dynamic adjustment of participating threads

  2. Core Concepts:

    • Phase: Numbered starting from 0, increments after all threads complete
    • Registration: Dynamically increases or decreases participating thread count
  3. Code Example:

public class PhaserDemo {
    public static void main(String[] args) {
        Phaser phaser = new Phaser(3) { // Initial 3 participating threads
            @Override
            protected boolean onAdvance(int phase, int registeredParties) {
                System.out.println("Phase " + phase + " completed");
                return registeredParties == 0; // Returns true to terminate Phaser
            }
        };
        
        for (int i = 1; i <= 3; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + " Completed phase 0");
                phaser.arriveAndAwaitAdvance(); // Wait for other threads
                
                System.out.println(Thread.currentThread().getName() + " Completed phase 1");
                phaser.arriveAndAwaitAdvance();
                
                phaser.arriveAndDeregister(); // Complete task and deregister
            }, "Thread" + i).start();
        }
    }
}

VII. Tool Class Comparison Summary

Tool Class Core Function Reusability Characteristics
CountDownLatch Wait for specified number of tasks to complete No Single-use, main thread waits
CyclicBarrier Mutual waiting among threads Yes Reusable, supports barrier action
Semaphore Control resource access quantity Yes Supports fair/non-fair modes
Exchanger Data exchange between threads Yes Supports exchange between only two threads
Phaser Multi-phase task synchronization Yes Most flexible, supports dynamic adjustment

VIII. Usage Scenario Analysis

  1. CountDownLatch: Main thread waits for all subtasks to complete
  2. CyclicBarrier: Multi-threaded computation, merging calculation results
  3. Semaphore: Database connection pool rate limiting
  4. Exchanger: Data verification between two threads
  5. Phaser: Complex multi-phase task coordination

These utility classes provide higher-level thread coordination mechanisms than wait/notify, simplifying development of complex concurrency scenarios.