【问题标题】:Confused about ThreadLocal对 ThreadLocal 感到困惑
【发布时间】:2012-06-25 17:17:53
【问题描述】:

我今天早上刚刚了解了 ThreadLocal。我读到它应该始终是最终的和静态的,例如:

private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();

(会话是一个休眠会话)

我的困惑是:因为它是静态的,它可用于 JVM 中的任何线程。然而,它会为每个访问它的线程保存本地信息吗?我正试图解决这个问题,所以如果不清楚,我深表歉意。应用程序中的每个线程都可以访问同一个 ThreadLocal 对象,但是 ThreadLocal 对象会存储每个线程本地的对象?

【问题讨论】:

  • 小心在共享环境中部署的 Web 应用程序中使用它。本地线程将在所有上下文中泄漏,并且在取消部署后,本地线程中的引用将不会被垃圾收集。您需要在每次请求后手动删除数据。
  • 看似矛盾。 ThreadLocal 在每个线程中应该是唯一的,但静态对象在每个线程之间共享。正要问同样的问题。

标签: java thread-local


【解决方案1】:

是的,实例将是相同的,但代码会在您设置和检索时附加您使用 Thread.currentThread() 设置的值,因此当使用方法setget

真的很容易理解。

想象一下,每个Thread 都有一个将值与ThreadLocal 实例相关联的映射。每次在 ThreadLocal 上执行 get 或 set 时,ThreadLocal 的实现会获取与当前 Thread (Thread.currentThread()) 关联的映射,并使用该映射执行 getset自己作为键。

示例:

ThreadLocal tl = new ThreadLocal();
tl.set(new Object()); // in this moment the implementation will do something similar to Thread.getCurrentThread().threadLocals.put(tl, [object you gave]) 

Object obj = t1.get(); // in this moment the implementation will do something similar to Thread.getCurrentThread().threadLocals.get(tl)

有趣的是 ThreadLocal 是分层的,这意味着如果您为父级 Thread 定义了一个值,它将可以从子级访问。

【讨论】:

  • 你说想象ThreadLocal中有一张地图。我明白了这个概念。线程 id 是键,唯一实例是值。所以整个ThreadLocal 对象是静态的,每个线程保存一个值。它实际上是用内部地图实现的吗?
  • 我只是查看了源代码。它有一个内部地图。 grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/…
【解决方案2】:

您总是针对特定问题访问同一个 ThreadLocal 实例,但该实例为调用 get 方法的每个线程返回不同的值。

这就是重点:找到对象很容易,但每个线程都有自己特定的值。例如,您可以确保您的特定值不会被两个不同的线程访问。

您可以(从概念上)将其视为一种HashMap&lt;Thread&gt;&lt;V&gt;,始终使用Thread.currentThread() 作为键来访问它。

【讨论】:

    【解决方案3】:

    因为线程特定的值不是存储在ThreadLocal对象中,而是current ThreadThreadLocalMapThreadLocal 对象仅用作这些映射中的键。

    有关详细信息,请阅读 ThreadLocal 及其子类的 JavaDoc,或者,如果您对实现感到好奇,请阅读每个最新 JDK src.zip 中提供的源代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-13
      • 2012-07-22
      • 2013-05-13
      • 2020-04-16
      • 2023-03-08
      • 2019-08-04
      • 2019-12-30
      • 2022-01-20
      相关资源
      最近更新 更多