How does ScopedValue improve on ThreadLocal for use with virtual threads?
ThreadLocal keeps a separate map per thread, which is manageable with a modest number of platform threads but becomes a real problem with virtual threads, where an application might have a million of them running: a million separate ThreadLocal maps adds up to significant heap overhead. Values also have to be cleaned up manually by calling remove(), and forgetting to do so leaks context between reuses. There's also no efficient built-in way to have a value automatically inherited by child virtual threads, since InheritableThreadLocal is both mutable and comparatively expensive to propagate. ScopedValue, introduced in Java 21, addresses all of this: its values are stored as part of a scope structure rather than duplicated per thread, so memory overhead stays minimal no matter how many threads exist; the value is automatically cleaned up the moment the scope exits, eliminating the leak risk entirely; child virtual threads automatically and efficiently inherit their parent's ScopedValues; and values are immutable for the duration of a scope, ruling out accidental mutation. For any new code targeting Java 21 or later, ScopedValue should generally be preferred over ThreadLocal.
Ready to master this question?
Generate a complete walkthrough — background, the full answer in plain language, a working code example explained line by line, a real-world scenario, common mistakes, and how this same question gets asked in different ways.
Sign in to generate a response