2012-06-25 202 views
6

今天早上我刚刚了解了ThreadLocal。我读了它应该永远是最终的,静态的,如:关于ThreadLocal的困惑

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

(Session是一个Hibernate的Session)

我的困惑是这样的:因为它是静态的,它是提供给在JVM中的任何线程。然而,它将持有访问它的每个线程的本地信息?我试图围绕这一点,所以我很抱歉,如果这不清楚。应用程序中的每个线程都可以访问同一个ThreadLocal对象,但ThreadLocal对象将存储每个线程本地的对象?

+3

请小心在共享环境中部署的Web应用程序中使用此功能。线程本地将在所有上下文中泄漏,并且在取消部署之后,线程本地中的引用将不会被垃圾收集。您需要手动删除每个请求后的数据。 – jontro

+0

看似矛盾。 'ThreadLocal'在每个线程中应该是唯一的,但是静态对象在每个线程之间共享。正要问这个同样的问题。 – aliteralmind

回答

10

是的,实例将是相同的,但代码将您设置的值与Thread.currentThread()相关联,当您设置和检索时,所以只有在使用方法访问时,值集才可在当前线程内访问setget

它很容易理解它。

想象一下,每个Thread都有一个将值关联到ThreadLocal实例的映射。每当您在ThreadLocal上执行获取或设置时,实施ThreadLocal都会获取与当前的ThreadThread.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值时,它会从一个孩子一个通达之意。

+0

谢谢,这有助于很多。 – badgerduke

+0

不客气! –

+0

你说你想象一下'ThreadLocal'中有一张地图。我明白了。线程ID是键,唯一的实例是值。所以总的'ThreadLocal'对象是静态的,并且每个线程保存一个值。它是否实际使用内部映射来实现? – aliteralmind

2

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

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

你可以看到它(概念上)作为一种HashMap<Thread><V>,总是可以用Thread.currentThread()作为键来访问它。

+0

谢谢你的回应! – badgerduke

2

因为线程特定的值没有存储在ThreadLocal对象中,而是current ThreadThreadLocalMap。这些物体仅仅作为这些地图中的关键。

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

+0

谢谢,这有帮助! – badgerduke