Virtual Threads
Mastering Lightweight Concurrency for Modern Java Applications
Master the next generation of Java concurrency with Virtual Threads and build applications that handle millions of concurrent operations with minimal resource overhead.
222 pages10 chaptersAug 4, 2026Java
About this book
You'll discover how Virtual Threads simplify concurrent programming by making the familiar thread-per-request model practical again, eliminating the complexity of reactive frameworks while delivering superior performance. This guide walks you through the fundamentals of Virtual Threads, their architecture, and how they differ from traditional platform threads. Learn to design systems that leverage structured concurrency for safe, predictable behavior, implement real-world patterns for I/O-bound workloads, and integrate Virtual Threads into existing applications without major refactoring. Whether you're building microservices, APIs, or data processing systems, you'll gain the knowledge to architect solutions that scale efficiently while keeping your code clean and maintainable.
Table of contents
- IntroductionWhy Virtual Threads Matter Now, What You'll Learn in This Book, Prerequisites and How to Use This GuideRead below
- Chapter 1: The Evolution of Java ConcurrencyFrom Green Threads to Platform Threads, The Scalability Challenge: Why Threads Became Expensive, The Reactive Programming Response, Virtual Threads: A New Paradigm
- Chapter 2: Understanding Virtual Threads FundamentalsWhat Are Virtual Threads?, Virtual Threads vs. Platform Threads: Key Differences, Carrier Threads and the Scheduler, Memory and Resource Efficiency
- Chapter 3: Creating and Managing Virtual ThreadsCreating Virtual Threads: Thread.ofVirtual(), Customizing Virtual Threads with Builders, Virtual Thread Lifecycle and State Management, Naming and Debugging Virtual Threads
- Chapter 4: Structured Concurrency and SafetyIntroduction to Structured Concurrency, Scope and Lifecycle Management, Exception Handling in Concurrent Contexts, Cancellation and Timeout Patterns
- Chapter 5: I/O-Bound Workloads and Virtual ThreadsIdentifying I/O-Bound Workloads, Why Blocking I/O Works Well with Virtual Threads, Network Operations and HTTP Clients, Database Access Patterns
- Chapter 6: Synchronization and Shared StateThread Safety Fundamentals, Locks, Monitors, and Virtual Threads, Concurrent Collections and Data Structures, Understanding Thread Pinning and Its Impact
- Chapter 7: Building Scalable ApplicationsRethinking Thread Pools for Virtual Threads, ExecutorService and Virtual Thread Executors, Resource Management at Scale, Backpressure and Flow Control
- Chapter 8: Real-World Patterns and Best PracticesWeb Server and REST API Patterns, Microservices Architecture with Virtual Threads, Batch Processing and Data Pipeline Patterns, Best Practices and Common Pitfalls
- Chapter 9: Monitoring, Observability, and PerformanceObservability Challenges with Millions of Threads, JVM Monitoring and Profiling Tools, Collecting and Analyzing Metrics, Performance Tuning and Optimization
- Chapter 10: Migration and Integration StrategiesAssessing Your Application for Virtual Threads, Incremental Migration Approaches, Compatibility and Library Considerations, Testing Strategies for Virtual Thread Applications
- ConclusionKey Takeaways, The Future of Java Concurrency
- Glossary
- Further Reading and Resources
Introduction
Java applications have been wrestling with the same fundamental tension for decades: threads are the natural unit of concurrent work, but they are expensive. A typical Platform Thread on the JVM maps one-to-one to an operating system thread, which carries a stack size measured in megabytes and a scheduling cost that compounds quickly. Run a few hundred threads and your application hums along. Push toward ten thousand, and memory pressure, context-switching overhead, and OS scheduler limits start to bite hard. This ceiling has shaped how Java developers write concurrent code for a long time, often pushing them toward workarounds that trade simplicity for scale.
Java 21 changed the equation. Virtual Threads, delivered as a production-ready feature through Project Loom, decouple the concept of a thread from the OS-level resource that backs it. A Virtual Thread is a lightweight abstraction managed by the JVM rather than the operating system. You can create millions of them in a single process without exhausting memory or overwhelming the scheduler. The mechanics behind this shift are significant, but the practical consequence is even more so: the thread-per-request model, long considered too costly for high-throughput services, becomes viable again.[1]
That viability matters because the thread-per-request model is simple. Each incoming request gets its own thread. The code runs top to bottom, blocking when it needs to wait for a database or a remote service, and the thread is released when the work is done. Developers can read the stack trace, set a breakpoint, and reason about the flow without mental gymnastics. Reactive Programming frameworks offered a path to scale, but they demanded a fundamentally different programming style, one built around callbacks, pipelines, and non-blocking APIs that many teams found difficult to adopt, debug, and maintain. Virtual Threads offer a third path: the simplicity of blocking code at the scale of reactive systems.
This book is a practical guide to that third path. It covers the architecture behind Virtual Threads, the APIs you use to create and manage them, the patterns that make them effective in production, and the pitfalls that can undermine their benefits if left unaddressed. Whether you are building a new service from scratch or modernizing an existing application, the goal is to give you a clear, grounded understanding of how Virtual Threads work and how to put them to work.
Why Virtual Threads Matter Now
The timing of Virtual Threads is not accidental. Modern applications are overwhelmingly I/O-Bound Workloads. A web service handling a user request might query a database, call two downstream APIs, read from a cache, and write to a message queue before sending a response. During each of those operations, the thread doing the work is simply waiting. With a Platform Thread, that waiting is expensive because the OS thread is parked but still consumes its full memory allocation and holds a slot in the scheduler's attention. With a Virtual Thread, the JVM detects the blocking point, unmounts the virtual thread from its Carrier Thread, and immediately reuses that carrier for other work.
This unmounting behavior is the core insight. The Carrier Thread, which is a real OS thread, never actually blocks. It keeps running other Virtual Threads while the original one waits for its I/O to complete. The result is that a small pool of Carrier Threads can serve an enormous number of Virtual Threads concurrently, because at any given moment most of those virtual threads are waiting rather than computing. A service that previously needed a thread pool capped at 200 threads to avoid memory exhaustion can now handle tens of thousands of concurrent requests with the same hardware.
The business case for this shift is straightforward. Higher concurrency on the same hardware means lower infrastructure costs. Simpler code means faster development and fewer bugs. Easier debugging means shorter incident resolution times. These are not abstract benefits. Teams that have adopted Virtual Threads in production report being able to retire reactive frameworks and return to straightforward imperative code without sacrificing throughput.[2]
There is also a timing argument rooted in ecosystem readiness. Java 21 is a Long-Term Support release, which means enterprise teams can adopt it with confidence in its stability and support window. Major frameworks including Spring Boot, Quarkus, and Micronaut have added first-class support for Virtual Threads. JDBC drivers, HTTP clients, and most standard library blocking operations already cooperate with the JVM scheduler correctly. The infrastructure around Virtual Threads has matured to the point where production adoption is not a leap of faith but a calculated upgrade.
Understanding why Virtual Threads matter also requires understanding what they do not change. They are not a solution for CPU-bound work. If your threads are spending their time computing rather than waiting, adding more threads does not help and may hurt. Virtual Threads do not eliminate the need to think about Thread Safety or shared mutable state. They do not make poorly designed code fast. The concurrency model changes; the discipline required to write correct concurrent code does not. Knowing these boundaries is as important as knowing the capabilities.
Consider a concrete comparison. A traditional thread pool serving HTTP requests might be configured with 200 threads. If each request takes 100 milliseconds and 80 of those milliseconds are spent waiting on a database query, the pool can theoretically handle 200 requests every 100 milliseconds, or 2,000 requests per second. With Virtual Threads, those 80 milliseconds of waiting are freed up for other virtual threads to run. The same hardware can now handle far more concurrent requests, limited not by thread count but by actual CPU and I/O capacity. That is the practical difference Virtual Threads make.
The shift also has implications for how teams think about architecture. Patterns that were previously reserved for reactive systems, such as fan-out calls to multiple services or parallel data enrichment pipelines, become straightforward to implement with blocking code and Virtual Threads. Structured Concurrency, covered in depth later in this book, provides a disciplined framework for managing those patterns safely. The combination of Virtual Threads and Structured Concurrency represents a genuine step forward in how Java handles concurrent work.
Virtual Threads do not make threads free. They make threads cheap enough that the thread-per-request model scales to modern workloads without requiring a different programming paradigm.
That distinction is worth holding onto as you read. Virtual Threads are not magic. They are a well-engineered solution to a specific problem: the mismatch between the cost of OS threads and the number of concurrent tasks that modern applications need to handle. Understanding that problem clearly is the foundation for using the solution well.
What You'll Learn in This Book
This book is organized to build understanding progressively, starting with context and fundamentals, moving through APIs and patterns, and finishing with production concerns like observability and migration. Each chapter focuses on a distinct aspect of working with Virtual Threads, and the concepts build on each other in a deliberate sequence. Here is a map of the ground covered.
The first chapter traces the historical arc of Java concurrency. It covers the journey from early Green Threads through the Platform Thread model that has dominated Java for most of its history, through the rise of Reactive Programming as a response to scalability limits, and finally to the breakthrough that Virtual Threads represent. Understanding this history is not just background. It explains why certain design decisions were made and why Virtual Threads are structured the way they are.
The second chapter goes deep on fundamentals. It explains what a Virtual Thread actually is at the JVM level, how it differs from a Platform Thread in terms of memory layout and scheduling, what Carrier Threads are and how the JVM Scheduler assigns virtual threads to them, and why the memory footprint of a Virtual Thread is so much smaller than its platform counterpart. This chapter gives you the mental model you need to reason about Virtual Thread behavior in real applications.
The third chapter covers the API surface for creating and managing Virtual Threads. You will see how to use Thread.ofVirtual() and Executors.newVirtualThreadPerTaskExecutor(), how to configure threads with builders, how to manage the Thread Lifecycle, and how to name and inspect threads for debugging purposes. This is the hands-on foundation for everything that follows.
The fourth chapter addresses Structured Concurrency, which is the discipline of managing groups of Virtual Threads as a unit. Using StructuredTaskScope, you can scope the lifetimes of concurrent subtasks, propagate exceptions cleanly, and cancel work that is no longer needed. This chapter shows why unstructured concurrency leads to resource leaks and unpredictable behavior, and how the structured approach solves those problems with concrete code examples.
The fifth chapter focuses on I/O-Bound Workloads, which is where Virtual Threads deliver their most dramatic benefits. It covers why blocking I/O is the ideal workload, how to apply that insight to network operations and HTTP clients, and how to handle database access patterns effectively. Real-world scenarios illustrate the difference between naive and optimized approaches.
The sixth chapter tackles synchronization and shared state. Thread Safety does not go away with Virtual Threads, and this chapter covers the fundamentals of locks and monitors in a virtual thread context, the role of Concurrent Collections, and the specific hazard of Thread Pinning. Thread Pinning occurs when a Virtual Thread cannot be unmounted from its Carrier Thread, typically because it holds a monitor lock inside a synchronized block. Understanding when and why pinning happens is essential for avoiding performance regressions.
The seventh chapter rethinks thread pools and Resource Management at scale. With Virtual Threads, the old advice of carefully sizing thread pools no longer applies in the same way. This chapter explains how to redesign executor strategies, how to use Executors.newVirtualThreadPerTaskExecutor() effectively, and how to implement Backpressure and flow control to prevent runaway resource consumption when virtual threads are created at high rates.
The eighth chapter moves into real-world patterns. It covers web server and REST API patterns, microservices architectures built on Virtual Threads, batch processing and data pipeline designs, and a consolidated set of best practices alongside common pitfalls. Each pattern is grounded in concrete scenarios with specific implementation guidance.
The ninth chapter addresses observability. Running millions of Virtual Threads creates new challenges for monitoring and profiling. This chapter covers the tools available, including Java Flight Recorder, how to collect and analyze metrics at scale, and how to tune performance when something is not working as expected.
The tenth and final chapter covers Incremental Migration. Most teams are not starting from scratch. This chapter provides a systematic approach to assessing an existing application, migrating incrementally without breaking things, handling compatibility concerns with libraries that may not yet cooperate with Virtual Threads, and testing strategies that give you confidence in the migration.
Prerequisites and How to Use This Guide
This book assumes you are comfortable with Java as a language and have some experience with concurrent programming. You do not need to be an expert in concurrency, but you should be familiar with the basics: creating threads, using ExecutorService, understanding what a race condition is, and knowing why synchronized exists. If those concepts are unfamiliar, a foundational concurrency resource will serve you better as a starting point before returning here.
Specifically, the assumed baseline includes the following:
- Comfort with Java syntax through at least Java 11, including lambdas and the
java.util.concurrentpackage - A working understanding of what threads are and why concurrent code requires careful coordination
- Familiarity with common concurrency primitives such as locks, semaphores, and thread pools
- Some exposure to building server-side Java applications, whether REST APIs, microservices, or batch jobs
- Basic awareness of I/O operations and why they can block a thread
You do not need prior experience with Reactive Programming or Project Loom. The book explains reactive concepts where they provide useful contrast, but it does not assume you have built reactive applications. If you have, that background will add useful context, particularly in the chapters on I/O-Bound Workloads and migration.
To run the code examples in this book, you need Java 21 or later. Java 21 is the first Long-Term Support release in which Virtual Threads are fully production-ready, with Structured Concurrency available as a preview feature that stabilizes in subsequent releases. Most examples will compile and run on Java 21 without additional flags. Where a feature requires a specific flag or a later version, the text notes it explicitly. Setting up a Java 21 environment is straightforward through tools like SDKMAN or by downloading directly from Adoptium or the official OpenJDK distribution.
The book is designed to be read sequentially on a first pass. The chapters build on each other, and concepts introduced early are assumed in later chapters without re-explanation. That said, once you have read through once, individual chapters work well as standalone references. If you are debugging a Thread Pinning issue in production, the synchronization chapter stands on its own. If you are planning a migration, the migration chapter is self-contained enough to be useful without re-reading everything before it.
Code examples throughout the book are written to be minimal and focused. They illustrate the concept at hand without surrounding noise. In a real application, you would add error handling, logging, configuration, and other production concerns. The examples strip those away deliberately so the relevant mechanism is visible. Where a pattern has important production considerations, the text calls them out explicitly rather than embedding them in the code.
Each chapter ends at a natural boundary rather than with a summary of what was covered. The goal is to leave you at the edge of the next concept rather than looking backward. Concurrency is a subject where the connections between ideas matter as much as the ideas themselves, and the structure of the book tries to honor that by keeping momentum forward.
A note on terminology: this book uses the canonical terms from the Virtual Threads specification consistently. Virtual Thread always refers to the JVM-managed lightweight thread. Platform Thread always refers to the OS-backed thread that Java has used historically. Carrier Thread refers to the Platform Thread that currently executes a Virtual Thread. These distinctions matter when reasoning about scheduling and performance, and using precise language throughout makes that reasoning cleaner. The glossary at the back of the book provides quick definitions for all key terms if you need a reference while reading.
One practical suggestion: as you work through the chapters on creating Virtual Threads and Structured Concurrency, run the examples yourself and experiment with variations. Concurrency behavior is often counterintuitive until you have seen it in action. Changing a thread count, introducing an artificial delay, or swapping a synchronized block for a ReentrantLock and observing the difference in behavior will build intuition faster than reading alone. The concepts in this book are not difficult to understand in isolation, but their interactions become clear through hands-on exploration.
The Java concurrency landscape has shifted meaningfully with Virtual Threads, and the shift is still unfolding. Frameworks are updating their internals, libraries are adding compatibility, and the JVM itself continues to evolve. What this book provides is a stable foundation: the core concepts, the reliable patterns, and the judgment to evaluate new developments as they arrive. The specifics of any given library version will change; the understanding of why Virtual Threads work the way they do will not.
This is the end of the free sample. The full book has 10 chapters.
Want this book written for you?
Tell us your goals and background, and get your own version of this book, tailored by AI to you.
Benefits of AI-tailored books
- Read one book, not ten:
- all the Java knowledge you need, gathered into a single book.
- Save days of learning:
- tell us your goals, choose your topics, and the whole book is built around them.
- Learn effortlessly:
- Java book written for your specific background and expertise.
- Understand at a glance:
- includes charts, tables, timelines, checklists, decision trees, and more.
- Stay current:
- written the day you order it, not years ago.
- Trust what you read:
- every book is checked for accuracy, with real research when your subject needs it.
Create your unique book in 3 steps
- 1. Select your focus
Select the focus of your Java book and share your background
- 2. Personalize your book
Specify your goals and choose sub-topics to include
- 3. Get your tailored book
Your book is ready in 10 minutes. Read it online, download as EPUB or PDF, or send to Kindle.
Frequently asked questions
- What is TailoredRead?
TailoredRead creates complete, full-length nonfiction ebooks, written specifically for you. Tell us what you want to learn and why, and TailoredRead writes you a complete ebook on it, with charts, tables, and diagrams throughout. Read it online, on Kindle, or on any e-reader, or download it as a PDF or EPUB. Every book is written fresh the day you order it.
- How is the book tailored to me?
Before anything is written, you answer a few short questions about your goals, your background, and the topics you care about. Your book is then planned around your answers: written at your level, focused on your goals, and covering the topics you chose, instead of the one-size-fits-all book a store sells everyone.
- Will it read like generic AI content?
No. Your book isn't a chat transcript: it's planned chapter by chapter before a single word is written, told in a clear book voice, and explains ideas visually with charts, tables, and diagrams. After writing, every book goes through an editorial pass that polishes chapters so the book reads consistent from start to finish. Judge for yourself: browse thousands of sample books on our Explore Books page.
- How accurate is the content?
Our AI first checks whether your subject needs live research. Niche and fast-moving subjects are researched before writing, and the book plan and chapters are grounded in what it finds. After writing, every book goes through a quality pass that checks its facts and consistency, and researched books list their sources in a Notes section at the back.
- How long is the book?
You choose the length: Comprehensive (250-300 pages), Detailed (150-200 pages), Essential (70-100 pages), or Short (30-50 pages).
- Does the book include visuals?
Yes. Every book includes visual elements such as timelines, checklists, step-by-step guides, decision trees, comparison tables, and matrices, and many include bar charts. A typical book includes dozens of these visual elements.
- Can I read it on Kindle? What formats can I download?
Yes. Every book can be read in our online reader or downloaded as a PDF or EPUB. The EPUB can be opened with Kindle, Apple Books, Kobo, and any e-reader. The Commercial and Author licenses also include an editable Word (DOCX) and Markdown download.
- How much does it cost?
About the price of a regular ebook. The exact price depends on your book's length and complexity, from $2 for the shortest books to $35 for the most comprehensive, and it's shown when you review your book, before you commit to anything. Each book is a one-time purchase, yours to keep, no subscription. Licenses that let you share, teach, or publish your book range from $35.99 to $49.99.
- Can I preview the book before purchasing?
Before you pay, you'll see what your book will cover: the title, a detailed description, the estimated length, and the complete chapter-by-chapter table of contents, so you know what you're getting before you decide. The full text itself is written after you purchase.
- How long does it take to create a book?
About 10 minutes. You can start reading the opening chapters while the rest is still being written.


