Skip to content

面试速答(先看这里)

**一句话结论:**虚拟线程是支持ThreadLocal的,但由于可能创建的虚拟线程数量巨大,不当使用ThreadLocal可能导致内存泄漏等问题。

60秒标准回答:

在使用虚拟线程的时候,不建议使用ThreadLocal,这是JDK官网文档中提到的

虚拟线程是支持ThreadLocal的,但由于可能创建的虚拟线程数量巨大,不当使用ThreadLocal可能导致内存泄漏等问题。如果需要,可以考虑使用作用域局部变量(Scope-local variables)作为替代方案

Scoped Values ,是JEP429中带来的一个特性,在JDK 21中已经推出了预览版。 是Java中一种提供在特定执行范围内共享变量的机制,这种机制旨在为虚拟线程和结构化并发提供更好的支持。 与ThreadLocal变量不同,作用域局部变量不是绑定到线程上的,而是绑定到特定的执行范围或上下文。 这使得在使用虚拟线程时,管理跨任务共享的状态变得更加方便和安全

**答题顺序:**结论 → 原理/机制 → 关键流程 → 场景与取舍 → 易错点

回答主线:

  • **要点1:**在使用虚拟线程的时候,不建议使用ThreadLocal,这是JDK官网文档中提到的。
  • **要点2:**Scoped Values ,是JEP429中带来的一个特性,在JDK 21中已经推出了预览版。
  • **要点3:**与 Thread Local 不同的是,Scoped Value的值是不可变的。
  • **要点4:**因为这个特性目前还是预览版,并没有正式推出(截止24.3),所以暂时不做过多介绍了,后续推出正式版了,特性语法确定了再展开吧。

**记忆锚点:**ThreadLocal → Scoped → JDK → Scope-local → 于可能创建的虚拟线程 → 范围内共享变量的机制

易错提醒:

  • 在使用虚拟线程的时候,不建议使用ThreadLocal,这是JDK官网文档中提到的。

加分表达:

  • 如果需要,可以考虑使用作用域局部变量(Scope-local variables)作为替代方案。

追问准备:

  • 围绕「ThreadLocal」:底层原理是什么?使用时有哪些边界和常见坑?
  • 围绕「Scoped」:底层原理是什么?使用时有哪些边界和常见坑?
  • 围绕「JDK」:底层原理是什么?使用时有哪些边界和常见坑?
  • 如果线上出现异常,你会如何定位、验证并规避?

典型回答 ​

在使用虚拟线程的时候,不建议使用ThreadLocal,这是JDK官网文档中提到的。

image.png

虚拟线程是支持ThreadLocal的,但由于可能创建的虚拟线程数量巨大,不当使用ThreadLocal可能导致内存泄漏等问题。如果需要,可以考虑使用作用域局部变量(Scope-local variables)作为替代方案。

Scoped Values,是JEP429中带来的一个特性,在JDK 21中已经推出了预览版。是Java中一种提供在特定执行范围内共享变量的机制,这种机制旨在为虚拟线程和结构化并发提供更好的支持。**与ThreadLocal变量不同,作用域局部变量不是绑定到线程上的,而是绑定到特定的执行范围或上下文。**这使得在使用虚拟线程时,管理跨任务共享的状态变得更加方便和安全。

与 Thread Local 不同的是,Scoped Value的值是不可变的。他的用法和ThreadLocal比较像:

javascript
class Server {
    final static ScopedValue<Principal> PRINCIPAL =  ScopedValue.newInstance(); 

    void serve(Request request, Response response) {
        var level     = (request.isAdmin() ? ADMIN : GUEST);
        var principal = new Principal(level);
        ScopedValue.where(PRINCIPAL, principal)                           
                   .run(() -> Application.handle(request, response));
    }
}

class DBAccess {
    DBConnection open() {
        var principal = Server.PRINCIPAL.get();                            
        if (!principal.canOpen()) throw new  InvalidPrincipalException();
        return newConnection(...);
    }
}

因为这个特性目前还是预览版,并没有正式推出(截止24.3),所以暂时不做过多介绍了,后续推出正式版了,特性语法确定了再展开吧。