京东自营 + 国补 iPhone 历史最低价          国家补贴 享8折

Java 25 新特性(一):Scoped Values,新的线程上下文传递机制,旨在替代传统的ThreadLocal

在 Java 25 中引入的Scoped Values是一种新的线程上下文传递机制,旨在替代传统的ThreadLocal,尤其适用于虚拟线程(Virtual Threads)场景。它解决了ThreadLocal在虚拟线程中存在的内存泄漏风险、状态污染和性能问题,提供了更安全、更轻量的线程局部状态管理方式。
Scoped Values 的核心特性
作用域限定:值的生命周期被严格限定在一个代码块(作用域)内,超出作用域后自动失效,避免内存泄漏。
不可变性:通常通过final定义,一旦在作用域中设置,无法被修改,保证线程安全。
可继承性:子线程(包括虚拟线程)可以自动继承父线程的 Scoped Values,无需手动传递上下文。
高效性:专为虚拟线程优化,比ThreadLocal更轻量,减少线程切换的开销。
与 ThreadLocal 的对比
ThreadLocal的问题在于:
线程池复用线程时,若未手动清理,会导致状态污染;
虚拟线程数量庞大时,ThreadLocal的哈希表实现会带来内存和性能压力;
可变性导致线程安全风险。
而 Scoped Values 通过作用域绑定和不可变性从根源上解决了这些问题。
应用实例:请求上下文传递
在 Web 服务中,常需要在请求处理的整个链路(可能涉及多个虚拟线程)中传递上下文信息(如用户 ID、请求 ID)。使用 Scoped Values 可以优雅地实现这一需求。
代码示例

import java.util.concurrent.Executors;
// 1. 定义Scoped Values(通常为静态常量)
public class ScopedValuesExample {
    // 定义两个Scoped Value:用户ID和请求ID
    private static final ScopedValue<String> USER_ID = ScopedValue.newInstance();
    private static final ScopedValue<String> REQUEST_ID = ScopedValue.newInstance();
    public static void main(String[] args) {
        // 模拟Web请求入口:设置Scoped Values的作用域
        String userId = "user_123";
        String requestId = "req_456";
        // 2. 通过ScopedValue.where()绑定值到作用域,在作用域内的代码(包括子线程)可访问
        ScopedValue.where(USER_ID, userId)
                   .where(REQUEST_ID, requestId)
                   .run(() -> handleRequest()); // 作用域内的核心逻辑
    }
    // 处理请求的核心方法
    private static void handleRequest() {
        System.out.println("主线程处理请求 - 用户ID: " + USER_ID.get() + ", 请求ID: " + REQUEST_ID.get());
        // 3. 在虚拟线程中访问父线程的Scoped Values
        try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
            // 子任务1:获取用户信息
            executor.submit(() -> {
                System.out.println("虚拟线程1 - 获取用户信息: " + USER_ID.get());
                return null;
            });
            // 子任务2:记录请求日志
            executor.submit(() -> {
                System.out.println("虚拟线程2 - 记录日志: " + REQUEST_ID.get());
                return null;
            });
        }
    }
}
展开阅读全文

本文系作者在时代Java发表,未经许可,不得转载。

如有侵权,请联系nowjava@qq.com删除。

编辑于

关注时代Java

关注时代Java