Try.withTimeout uses virtual threads (Thread.ofVirtual())
Context
Try.withTimeout needs to run user-supplied code with a wall-clock deadline. Options were:
- Platform threads via
ExecutorService - Virtual threads via
Thread.ofVirtual() CompletableFuturewith a shared pool
Decision
Use Thread.ofVirtual().start(task) to spawn a lightweight carrier for the timed operation. The calling thread blocks on FutureTask.get(timeout, unit) and interrupts the virtual thread on timeout.
Consequences
- No
ExecutorServicelifecycle to manage; threads are fire-and-forget. - Near-zero overhead for blocking I/O inside the timeout block (virtual thread parks, not blocks a carrier).
- The
CancellationExceptionbranch (external cancellation of the internalFutureTask) is unreachable from outside the method — accepted as an untestable defensive guard. - Requires Java 21+ (virtual threads GA); already met by the Java 25 baseline (ADR-001).
Alternatives considered
- Platform threads via
ExecutorService: requires lifecycle management and heavier overhead for blocking I/O. CompletableFuturewith a shared pool: uses the common ForkJoin pool, which is inappropriate for blocking operations.