Runtime AtlasJava platform fieldbook
Java · Language to RuntimeView Markdown source

Concurrency and virtual threads

Concurrency allows tasks to overlap. Correctness comes before throughput.

Threads and tasks

Prefer submitting tasks to an ExecutorService over manually creating platform threads. Shut executors down and handle interruption. Future represents a result available later; CompletableFuture composes asynchronous stages.

Shared-state hazards

A race occurs when outcome depends on timing. volatile gives visibility and ordering for a variable but does not make compound actions such as count++ atomic. Use locks, atomic types, concurrent collections, confinement, or immutable messages.

Every lock design needs ownership, ordering, timeout/interruption policy, and minimal critical sections. Lock-order cycles can deadlock.

Virtual threads

Virtual threads are lightweight Java threads finalized in Java 21. They are excellent for large numbers of mostly blocking I/O tasks while preserving a simple thread-per-task style.

They do not make CPU work faster and should not be pooled as scarce resources. Bound the actual scarce resource—database connections, remote concurrency, or memory—with semaphores/pools. Avoid long pinning around native calls or synchronized regions that block scalability; use JFR to observe pinning.

try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
  var futures = requests.stream().map(r -> executor.submit(() -> call(r))).toList();
}

Structured concurrency remains a preview API in Java 25. Preview features require explicit compilation/runtime flags and may change.

Feynman check

Virtual threads are lightweight customer tickets, not extra cashiers. They let many customers wait cheaply, but the database counter still serves only a limited number at once.

Runtime AtlasIndependent study material · verify production details in official Java documentation