Scoped Values in Java

Last Updated : 25 May, 2026

Scoped Values in Java provide a safe and efficient way to share immutable data within a limited scope across methods and threads. They are especially useful in modern concurrent and virtual-thread-based applications, helping maintain clean and structured data flow.

  • ScopedValue bindings are immutable and safely shared across threads, but thread safety also depends on the immutability of the stored object.
  • They allow efficient data sharing between parent and child threads without manually passing parameters.
  • They act as a lightweight alternative to ThreadLocal, improving performance in high-concurrency environments.

Syntax

ScopedValue<T> KEY = ScopedValue.newInstance();
ScopedValue.where(KEY, value)
.run(() -> {

// code where scoped value is accessible

});

  • ScopedValue<T> : Defines a scoped variable with type T (like String, Integer).
  • KEY : Identifier used to access the scoped value.
  • ScopedValue.newInstance() : Creates a new scoped value object.
  • ScopedValue.where(KEY, value) : Binds a value to the scoped variable for a limited scope.
  • value : The actual data stored in the scoped variable.
  • .run(() -> { ... }) : Code block where the scoped value is accessible.

Example

Java
import java.lang.ScopedValue;

public class ScopedValueDemo {

    static final ScopedValue<String> USER = ScopedValue.newInstance();

    public static void main(String[] args) {

        ScopedValue.where(USER, "Hello, Scoped World!")
            .run(() -> {
                System.out.println("Main: " + USER.get());
                child();
            });
    }

    static void child() {
        System.out.println("Child: " + USER.get());
    }
}

Output
Main: Hello, Scoped World!
Child: Hello, Scoped World!

Explanation: The program binds the value "Hello, Scoped World!" to the USER ScopedValue inside the where() scope. Within that scope, both main and child methods can access the same scoped binding using USER.get() within the active scope, but it is not accessible outside the scope.

Why we need Scoped Values?

  • They allow safe sharing of immutable data across methods and threads without passing parameters manually.
  • They are useful for passing data like user identity or permissions in web applications across multiple components.
  • They provide a modern alternative to ThreadLocal, avoiding its complexity, memory leaks, and thread-safety issues.

Problems with Thread Local Variables

  • They are mutable, so any code with access can change their values, making debugging difficult.
  • They can cause memory leaks because values may stay in memory until the thread ends if not manually cleared.
  • They have high inheritance cost, as each child thread must allocate and copy ThreadLocal values, reducing performance in large-scale applications.

Advantages

  • ScopedValue bindings are immutable, preventing reassignment within the scope. Safe sharing also depends on the immutability of the stored object.
  • They allow safe and structured data sharing across methods and threads without passing parameters manually.
  • They provide a clean alternative to ThreadLocal, reducing complexity in concurrent programming.
  • They improve performance and scalability in applications using virtual threads.
  • They help in better code readability and maintainability by limiting data scope clearly.

Limitation

  • They are a new preview feature, so API and behavior may change in future Java versions.
  • They support only immutable data, so you cannot modify values after binding.
  • They are not a full replacement for ThreadLocal in all use cases.
  • They have limited documentation and ecosystem support compared to older concurrency tools.
  • They may add slight learning complexity for beginners in multithreaded programming.
Comment