← Java Terms Explained

Scoped Values

Scoped Values, finalised in Java 24 (JEP 487), provide a mechanism to share immutable data within and across threads in a structured, predictable way — designed as a safer and more scalable alternative to ThreadLocal in the era of virtual threads.

A ScopedValue binds a value for the duration of a delimited scope (a lambda or method call). Any code executing within that scope — including code in child threads spawned via structured concurrency — can read the value. When the scope exits, the binding is automatically removed.

static final ScopedValue<User> CURRENT_USER = ScopedValue.newInstance();

ScopedValue.where(CURRENT_USER, authenticatedUser)
    .run(() -> {
        // Any code here, including virtual threads, can read CURRENT_USER.get()
        processRequest();
    });

The key advantages over ThreadLocal:

  • Immutable — a scoped value cannot be mutated after binding, eliminating a class of hidden-state bugs.
  • Structured lifetime — the binding is automatically removed when the scope exits, with no risk of thread pool leakage.
  • Virtual-thread friendly — with millions of virtual threads, per-thread mutable state is expensive; immutable scoped values are shared cheaply.

Scoped Values are designed to work in conjunction with Structured Concurrency and Virtual Threads.

See Also

Found a mistake, or something to add? Edit this page on GitHub

Join the discussion

← Back to all terms