Java
Top 100 Java Virtual Threads Interview Questions
A concise collection of the top 100 Java Virtual Threads interview questions with short, crisp answers for quick preparation.
-
What are Virtual Threads in Java? Lightweight threads managed by the JVM (not the OS), introduced as a final feature in Java 21 (JEP 444) via Project Loom. They enable high concurrency with minimal resource overhead.
-
What problem do Virtual Threads solve? They solve the scalability issues of platform threads for I/O-bound workloads, allowing millions of concurrent tasks without the memory and scheduling costs of OS threads.
-
How do Virtual Threads differ from Platform Threads? Platform threads map 1:1 to OS threads (expensive, ~1MB stack). Virtual threads are JVM-scheduled, multiplexed onto fewer carrier threads, and unmount during blocking I/O.
-
What is a Carrier Thread? A platform (OS) thread onto which the JVM mounts a virtual thread for execution. Virtual threads can be mounted/unmounted from different carriers over their lifetime.
-
What is Project Loom? The OpenJDK project that introduced virtual threads, structured concurrency, and scoped values to improve Java's concurrency model.
-
In which Java version were Virtual Threads finalized? Java 21 (JEP 444). They were previewed in Java 19 and 20.
-
Are Virtual Threads faster than Platform Threads? No. They do not speed up CPU-bound work. Their benefit is in scalability for blocking I/O tasks through efficient unmounting.
-
What is the typical memory footprint of a Virtual Thread? Starts small (a few hundred bytes to a few KB) and grows on demand, compared to ~1MB fixed for platform threads.
-
How many Virtual Threads can you create? Millions, limited mainly by available heap memory rather than OS thread limits.
-
How do you create a Virtual Thread?
Thread.startVirtualThread(() -> { ... });orThread.ofVirtual().start(...);or viaExecutors.newVirtualThreadPerTaskExecutor(). -
What is
Executors.newVirtualThreadPerTaskExecutor()? An executor that creates a new virtual thread for each submitted task. Prefer this over pooling virtual threads. -
Should you pool Virtual Threads? No. They are cheap to create. Pooling defeats their purpose. Use one per task and limit concurrency via semaphores or admission control if needed.
-
What happens when a Virtual Thread blocks on I/O? It is unmounted from its carrier thread. The carrier is free to run another virtual thread. The original is remounted when I/O completes.
-
What is pinning in the context of Virtual Threads? When a virtual thread cannot be unmounted from its carrier during a blocking operation, holding the carrier hostage and reducing scalability.
-
What causes pinning in Java 21? Blocking inside a
synchronizedblock/method, or while executing native methods/foreign functions (JNI/FFM). -
Was the synchronized pinning issue fixed? Yes, in JDK 24 (JEP 491). On Java 25+, blocking inside synchronized no longer pins the carrier. Native calls still pin.
-
How do you detect pinning? Use JFR events (
jdk.VirtualThreadPinned), or (on older JDKs) the system property-Djdk.tracePinnedThreads=full(removed in later versions). -
How do you avoid pinning (pre-JDK 24)? Prefer
ReentrantLockoversynchronizedfor critical sections that may block. Avoid long-running native calls. -
Do Virtual Threads help with CPU-bound tasks? No. They share a limited set of carrier threads (typically one per core). CPU-bound work holds the carrier and does not benefit from unmounting.
-
When should you use Virtual Threads? For high-concurrency, I/O-bound workloads (HTTP servers, database calls, RPC) where the thread-per-request model is natural.
-
When should you NOT use Virtual Threads? For CPU-bound tasks, low-concurrency applications, or code with heavy pinning/native calls. Also avoid if you need strict thread affinity.
-
Are Virtual Threads daemon threads? Yes, always. The JVM can exit even if virtual threads are still running (unless non-daemon platform threads exist).
-
Do Virtual Threads have a name? Yes. By default, they get names like
VirtualThread-<id>. You can set a custom name viaThread.Builder. -
How do you check if a thread is virtual?
Thread.currentThread().isVirtual(). -
What is the scheduler for Virtual Threads? An internal
ForkJoinPool(work-stealing, FIFO for virtual threads) distinct from the common pool used by parallel streams. -
How many carrier threads are there by default? Typically equal to the number of available processors (
Runtime.getRuntime().availableProcessors()). -
How can you configure the number of carrier threads? Via system properties:
jdk.virtualThreadScheduler.parallelismandjdk.virtualThreadScheduler.maxPoolSize. -
What is a Continuation in the context of Virtual Threads? The underlying mechanism (from Project Loom) that allows a virtual thread's execution state to be saved and restored when unmounted/mounted.
-
Do Virtual Threads support
ThreadLocal? Yes, but use carefully. With millions of threads, large ThreadLocals can consume significant memory. Prefer Scoped Values where possible. -
What are Scoped Values? A safer, more efficient alternative to ThreadLocals for immutable context (e.g., request-scoped data), finalized in Java 25. They work well with virtual threads.
-
What is Structured Concurrency? An approach (via
StructuredTaskScope) that treats a group of concurrent tasks as a single unit of work with clear lifecycle, cancellation, and error propagation. Preview in recent JDKs. -
How does Structured Concurrency relate to Virtual Threads? Subtasks in
StructuredTaskScopetypically run on virtual threads. It provides structure on top of the lightweight concurrency virtual threads enable. -
Can Virtual Threads replace reactive programming? For many I/O-bound use cases, yes. They allow simple blocking code with high scalability, reducing the need for reactive stacks (though reactive still has niches).
-
Do you still need connection pools with Virtual Threads? Yes. Virtual threads do not remove resource limits (DB connections, external rate limits). Use pools or semaphores to protect scarce resources.
-
How can Virtual Threads overload a database? By allowing far more concurrent requests than the DB can handle. Admission control (semaphores, rate limiters) is still required.
-
What is the recommended way to limit concurrency with Virtual Threads? Use a
Semaphoreor similar around the critical resource, or a bounded queue/admission controller, rather than a fixed thread pool. -
Are there any issues with
synchronizedand Virtual Threads on Java 21-23? Yes. Blocking while holding a monitor pins the carrier. Prefer short critical sections orReentrantLock. -
How does the JVM handle synchronous file I/O with Virtual Threads? In some cases, it may temporarily increase the number of carrier threads (up to maxPoolSize) because file I/O may not unmount cleanly.
-
Can Virtual Threads be interrupted? Yes, the same way as platform threads (
interrupt(),isInterrupted()). -
Do Virtual Threads support
Thread.sleep()? Yes. Sleeping unmounts the virtual thread from its carrier. -
What is the difference between mounting and unmounting? Mounting attaches a virtual thread to a carrier for execution. Unmounting detaches it (saving state) when it blocks, freeing the carrier.
-
Is there affinity between a Virtual Thread and a Carrier? No. A virtual thread can be remounted on any available carrier after unmounting.
-
How does debugging work with Virtual Threads? Standard tools (debuggers, thread dumps, JFR) support them. Thread dumps show both virtual and carrier threads.
-
What does a thread dump look like with Virtual Threads? It lists virtual threads separately and shows which carrier they are mounted on (if any).
-
Can you use Virtual Threads with
CompletableFuture? Yes. You can submit work that runs on virtual threads. They complement rather than replace futures for some composition needs. -
Does Spring Boot support Virtual Threads? Yes. Spring Boot 3.2+ supports them. Enable via
spring.threads.virtual.enabled=true. -
How does enabling Virtual Threads affect a Spring MVC application? Each request can be handled by a virtual thread, restoring the simple thread-per-request model at high scale.
-
Are there migration steps from platform thread pools to Virtual Threads? Replace fixed pools with
newVirtualThreadPerTaskExecutor(), audit for pinning (especially pre-JDK 24), review ThreadLocal usage, and add resource limits. -
What is the impact of deep call stacks on Virtual Threads? Memory usage grows with stack depth (like platform threads). Very deep stacks reduce the "lightweight" advantage.
-
Can Virtual Threads deadlock? Yes, the same as platform threads if locks are acquired in inconsistent orders. Pinning can also create effective deadlocks under load.
-
How do you create a Virtual Thread with a custom name?
Thread.ofVirtual().name("my-vt").start(() -> { ... }); -
What is
Thread.ofVirtual()? A factory method returning aThread.Builderfor configuring and creating virtual threads. -
Are Virtual Threads always daemon? Yes. There is no way to create a non-daemon virtual thread.
-
What happens if only Virtual Threads are running when the main thread ends? The JVM exits (since they are daemons), unless other non-daemon threads exist.
-
How do locks from
java.util.concurrentbehave with Virtual Threads?ReentrantLock,Semaphore, etc., correctly unmount virtual threads when they block (unlike synchronized in Java 21-23). -
Is there a performance overhead to mounting/unmounting? Yes, a small one. For pure CPU work it can make virtual threads slightly slower than platform threads.
-
What is the role of the ForkJoinPool in Virtual Thread scheduling? It manages the carrier threads and uses work-stealing to distribute runnable virtual threads efficiently.
-
Can you set a custom scheduler for Virtual Threads? Not easily in standard usage. The scheduler is internal; custom schedulers were explored but not part of the final API for most users.
-
How does
Object.wait()interact with Virtual Threads? In Java 21 it could cause pinning or special handling; behavior improved in later releases. -
What JFR events are useful for Virtual Threads?
jdk.VirtualThreadStart,jdk.VirtualThreadEnd,jdk.VirtualThreadPinned,jdk.VirtualThreadSubmitFailed, etc. -
Does using Virtual Threads change the need for asynchronous programming? For many cases, no. Blocking code becomes scalable, so complex async/reactive styles can be simplified.
-
What is the main advantage of the Virtual Thread programming model? Write simple, sequential, blocking-looking code while achieving high concurrency.
-
Can Virtual Threads be used in GUI applications? Possible, but the primary value is in server-side, high-concurrency I/O scenarios. GUI event threads have different constraints.
-
How do you submit many tasks with Virtual Threads? Prefer
ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();thenexecutor.submit(...). -
What is the difference between
startVirtualThreadand the executor approach?startVirtualThreadis for fire-and-forget single threads. The executor is better for managing many tasks and shutdown. -
Do Virtual Threads support priority? Virtual threads do not use the traditional priority mechanism in the same way; scheduling is handled by the JVM scheduler.
-
Can a Virtual Thread call native code? Yes, but native frames pin the virtual thread to its carrier for the duration of the call.
-
What is the Foreign Function & Memory API's relation to pinning? Calls into native code via FFM also pin the virtual thread.
-
How does garbage collection interact with Virtual Threads? Virtual threads and their stacks are ordinary Java objects on the heap. GC treats them normally; large numbers increase GC pressure if long-lived.
-
Are Virtual Threads suitable for batch processing? For I/O-heavy batch jobs with high parallelism, yes. For pure compute, a fixed platform thread pool sized to cores is better.
-
What happens to a pinned Virtual Thread under high load? It holds a carrier, reducing available carriers. If many are pinned, throughput collapses (carrier starvation).
-
How do you mitigate carrier starvation? Eliminate pinning (upgrade to JDK 24+ or refactor synchronized), limit concurrent tasks, and monitor with JFR.
-
Can you use
parallel()streams with Virtual Threads? Parallel streams still use the common ForkJoinPool of platform threads. Virtual threads are separate; mixing requires care. -
What is the recommended executor for Virtual Threads in production?
Executors.newVirtualThreadPerTaskExecutor(). -
Does enabling Virtual Threads require code changes? Often minimal for pure I/O servers. Code with synchronized + blocking, heavy ThreadLocals, or fixed pools needs review.
-
How does timeout/cancellation work with Virtual Threads? Standard interruption and
Future.cancel(). Structured concurrency provides better cancellation propagation. -
What is
StructuredTaskScope? A preview API for structured concurrency that forks subtasks (typically on virtual threads) and joins them with failure policies. -
What are the two main policies in StructuredTaskScope?
ShutdownOnFailure(cancel others on first failure) andShutdownOnSuccess(cancel others on first success). -
Why is Structured Concurrency important with Virtual Threads? Virtual threads make it easy to create many tasks; structured concurrency ensures they have a clear lifetime and proper cleanup.
-
Can Virtual Threads be used with reactive libraries? Yes, but you lose some benefits. The ideal is to use blocking code on virtual threads instead of reactive for simplicity.
-
What is the memory overhead of a parked Virtual Thread? Very low — mainly the continuation state and any local variables on its stack.
-
How does the JVM decide to unmount a Virtual Thread? When it detects a blocking operation that has been adapted (most java.util.concurrent locks, I/O, sleep, etc.).
-
Are all blocking operations unmount-aware? Most JDK blocking operations are. Third-party native or poorly adapted libraries may not unmount cleanly.
-
What is the impact of using Virtual Threads on latency? Throughput improves under high concurrency; single-request latency is similar or slightly higher due to scheduling overhead.
-
Should you replace every thread pool with Virtual Threads? No. Keep platform thread pools for CPU-bound work. Use virtual threads for I/O-bound task-per-thread scenarios.
-
How do you name the carrier threads for debugging? They appear as
ForkJoinPool-1-worker-Nor similar. You can influence via system properties in some cases. -
What is the default behavior of virtual thread names? Automatically generated, sequential, e.g.,
VirtualThread-42. -
Can you observe Virtual Threads in VisualVM or similar tools? Yes, modern profilers and tools support virtual threads.
-
What is the relationship between Virtual Threads and green threads? Virtual threads are a modern, efficient implementation of the green-thread idea, with proper unmounting (unlike early Java green threads).
-
Do Virtual Threads change the Java Memory Model? No. The JMM remains the same. Synchronization and happens-before rules apply equally.
-
How do you handle context propagation with Virtual Threads? Prefer Scoped Values. ThreadLocals work but scale poorly in memory with huge numbers of threads.
-
What is a common anti-pattern with Virtual Threads? Creating a fixed-size pool of virtual threads, or using synchronized around blocking I/O on Java 21-23.
-
Can Virtual Threads be used in microservices? Excellent fit for I/O-bound microservices. Improves scalability of the classic request-handling model.
-
What monitoring is recommended when adopting Virtual Threads? Watch carrier thread utilization, pinning events (JFR), heap usage, and downstream resource saturation (DB, HTTP clients).
-
Is there a limit to how deep a Virtual Thread's stack can grow? Limited by available heap. Extremely deep recursion or call stacks can still OOM.
-
How does
Thread.currentThread()behave inside a Virtual Thread? Returns the virtual thread itself, not the carrier. -
Can you get the carrier thread from a Virtual Thread? Not directly via public API in normal use. Internals exist but should not be relied upon.
-
What is the main takeaway for interview candidates about Virtual Threads? They restore simple blocking code for high-scale I/O concurrency, but require awareness of pinning (especially on older JDKs), resource limits, and not using them for CPU work.
-
How has the pinning story evolved since Java 21? Synchronized pinning was removed in JDK 24. On modern JDKs the main remaining pinning risk is native code.
-
What should you say if asked “Are Virtual Threads a silver bullet?” No. They are a powerful tool for I/O-bound high concurrency that simplifies code, but you still need proper resource management, monitoring, and awareness of remaining limitations.