Java ThreadLocal类的目的和用途?

Java ThreadLocal类的目的和用途?,java,Java,我正在浏览课程文档,想知道在什么情况下可以使用它 首先,我认为它可以用于那些有第三方/遗留类并且希望处理同步问题的场景。然后我查看了ThreadLocal的其他示例,发现ThreadLocal在这方面没有帮助,因为在大多数情况下,我们只有一个对象,可以跨所有线程共享。这是正确的吗 通过进一步的理解,现在我可以考虑在以下场景中使用ThreadLocal类:每个线程需要一个单独的对象,如果特定线程与ThreadLocal中的对象交互,则每次都使用相同的对象,而不是创建一个新的对象 这是正确的还是我遗

我正在浏览课程文档,想知道在什么情况下可以使用它

首先,我认为它可以用于那些有第三方/遗留类并且希望处理同步问题的场景。然后我查看了ThreadLocal的其他示例,发现ThreadLocal在这方面没有帮助,因为在大多数情况下,我们只有一个对象,可以跨所有线程共享。这是正确的吗

通过进一步的理解,现在我可以考虑在以下场景中使用ThreadLocal类:每个线程需要一个单独的对象,如果特定线程与ThreadLocal中的对象交互,则每次都使用相同的对象,而不是创建一个新的对象


这是正确的还是我遗漏了什么?

ThreadLocal最常用于在应用程序服务器或servlet容器中实现每个请求的全局变量,其中每个用户/客户端请求由单独的线程处理

例如,Spring、Spring Security和JSF都有“上下文”的概念,通过它可以访问框架的功能。在每种情况下,该上下文都是通过依赖项注入(干净的方式)实现的,并且在DI不能或不会使用的情况下,作为
ThreadLocal
实现的

这对可维护性是不利的,因为它隐藏了依赖项,并且因为这样的容器使用线程池而直接导致问题。他们必须使用反射来删除请求之间的所有
ThreadLocal
实例,以避免来自一个请求的数据在另一个请求中出现(可能导致严重的安全问题)。有时它也会导致内存泄漏


基本上,这是一个功能,可以非常有用的黑客方式,但也非常危险。我建议您尽可能避免这种情况。

另一个常用的应用程序是针对需要同步但必须避免开销的对象的每线程缓存

例如:
SimpleDateFormat
不是线程安全的-no
Format
是。总是创建一个新实例是没有效率的。在多线程环境中的一个实例上进行同步也没有效率。解决办法是:

class Foo
    private final static ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<SimpleDateFormat>(){
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat(pattern);
        }
    };
    public void doStuff(){ 
        SimpleDateFormat df = threadLocal.get();
        // use df
    }
}
class-Foo
private final static ThreadLocal ThreadLocal=新ThreadLocal(){
受保护的SimpleDataFormat初始值(){
返回新的SimpleDataFormat(模式);
}
};
public void doStuff(){
SimpleDataFormat df=threadLocal.get();
//使用df
}
}

就性能而言,我不确定这是否真的是一个更好的解决方案。访问ThreadLocal也不是一个简单或廉价的操作。一边查看
ThreadLocal.get()
的源代码,另一边查看构造函数
SimpleDataFormat(String)
,则说明了另一件事。也支持我的观点。你也看过
ThreadLocalMap
的源代码了吗?我想说的是,决策应该基于基准或(更好的)分析,而不是假设,这一点非常重要。如果你有数据支持你的建议,那太好了。第一:你读过链接问题中的答案了吗?有一些基准。第二:我认为很明显,在以任何方式(即不限于ThreadLocal方法)缓存任何内容之前,必须衡量它是否真的值得付出努力,或者缓存是否更昂贵。从这个意义上讲,
ThreadLocal
只是一个工具——如果它对您的案例有好处的话——很好。如果没有-使用更好的工具。第三:当时我第一次看到了
DateFormat
的缓存,基准看起来非常积极。谢谢Michael..正如您所说,ThreadLocal最常用于在应用服务器或servlet容器中实现每个请求的全局变量。我的理解是,我们通常不在servlet中保留全局变量,因为它们在线程之间是可见的,这很危险。因此,threadlocal提供了一种方法,使得变量对于每个特定线程都是全局的。对吗?@MichaelBorgwardt ThreadLocal可以用来保存执行跟踪吗?@gaurav:我不知道你说的“执行跟踪”到底是什么意思,但它可以保存你想要的任何东西。