⚡ Modern Java Concurrency: Threads, Executors & Virtual Threads

⚡ Modern Java Concurrency: Threads, Executors & Virtual Threads

Understanding Java's multi-threading and concurrency mechanisms is essential for writing performant, safe, and maintainable applications. This post explores thread creation, synchronization, executors, modern virtual threads, common concurrency problems, and tools for diagnosing issues.

1. ๐Ÿงต Thread Creation

  • Extending Thread: Override run().
  • class MyThread extends Thread {
        public void run() {
            System.out.println("Thread running");
        }
    }
    new MyThread().start();
  • Implementing Runnable: Pass to Thread.
  • Runnable task = () -> System.out.println("Runnable running");
    new Thread(task).start();
  • Callable & Future: Return value from thread.
  • Callable<Integer> task = () -> 42;
    Future<Integer> future = Executors.newSingleThreadExecutor().submit(task);
    System.out.println(future.get());
  • Virtual Threads (Java 19+): Lightweight threads.
  • try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
        executor.submit(() -> System.out.println("Virtual thread running"));
    }

2. ๐Ÿ”’ Synchronization & Locks

Ensure only one thread accesses critical sections:

  • synchronized: Built-in object/method lock.
  • ReentrantLock / ReadWriteLock / StampedLock: Advanced locking.
  • Semaphores: Limit concurrent access.
  • CountDownLatch / Phaser / CyclicBarrier: Coordinate multiple threads.

3. ๐Ÿ— Executor Framework

  • Interfaces: Executor, ExecutorService, ThreadPoolExecutor
  • Factories:
    • newSingleThreadExecutor()
    • newFixedThreadPool(n)
    • newCachedThreadPool()
    • newScheduledThreadPool(n)
    • newVirtualThreadPerTaskExecutor() (Java 19+)
  • Methods:
    • execute(Runnable) - no result
    • submit(Runnable / Callable) - returns Future
    • invokeAll(Collection<Callable>) / invokeAny(...) - execute multiple tasks

4. ⚠️ Common Concurrency Problems

  • Deadlock: Two threads wait forever for each other's locks.
  • Thread 1: lock(A) then lock(B)
    Thread 2: lock(B) then lock(A) → deadlock
  • Race Condition: Multiple threads modify shared data concurrently.
  • int counter = 0;
    Runnable r = () -> counter++;
    // multiple threads increment → unexpected results
  • Starvation: Low-priority threads never run.
  • Livelock: Threads actively retry but never complete.

5. ๐Ÿ’พ Thread Diagnostics & Memory Issues

  • Thread dump: Snapshot of all threads.
  • Memory leaks: Objects remain in heap but unused. Causes:
    • Static references
    • Unclosed resources (streams, connections)
  • Tools: JProfiler, VisualVM, JConsole, Flight Recorder (JFR)

6. ๐Ÿ“ Summary Table of Thread Pools

Thread Pool Behavior Use Case
newFixedThreadPool(int n) Fixed threads. Tasks queued if busy. Predictable concurrency
newCachedThreadPool() Creates threads on demand, reuses idle ones. Short-lived tasks, bursts
newSingleThreadExecutor() Single worker thread sequential execution. Ordered tasks
newScheduledThreadPool(int n) Execute tasks periodically or with delay. Recurring/scheduled tasks
newVirtualThreadPerTaskExecutor() Lightweight virtual threads, thousands possible. High concurrency, scalable microservices

7. ๐Ÿ”— Modern Java Utilities

  • CompletableFuture: Async computation, combine multiple futures.
  • ForkJoinPool: Efficient for parallel streams / divide-and-conquer.
  • Structured Concurrency (Java 21+): Manage multiple tasks as a single unit with StructuredTaskScope.
  • Volatile & transient: Volatile for visibility, transient for skipping serialization.

8. ๐Ÿ“Š Visual Summary

Thread

Platform vs Virtual Thread

Deadlock

Thread waiting forever

Race

Shared data conflict

Labels: Java, Threads, Concurrency, Executor, Synchronization, Deadlock, Race Condition, Virtual Threads, Structured Concurrency

Comments

Popular posts from this blog

๐Ÿ› ️ The Code Hut - Index

๐Ÿ“˜ Distributed Systems with Java — Series Index

๐Ÿ›ก️ Thread-Safe Programming in Java: Locks, Atomic Variables & LongAdder