何时以及如何使用 ThreadLocal 变量?

何时应使用 ThreadLocal 变量?

如何使用?


答案 1

一种可能的(也是常见的)用途是,当您有一些不是线程安全的对象,但您希望避免同步对该对象访问时(我正在看您,SimpleDateFormat)。相反,请为每个线程指定自己的对象实例。

例如:

public class Foo
{
    // SimpleDateFormat is not thread-safe, so give one to each thread
    private static final ThreadLocal<SimpleDateFormat> formatter = new ThreadLocal<SimpleDateFormat>(){
        @Override
        protected SimpleDateFormat initialValue()
        {
            return new SimpleDateFormat("yyyyMMdd HHmm");
        }
    };

    public String formatIt(Date date)
    {
        return formatter.get().format(date);
    }
}

文档


答案 2

由于 a 是对给定数据的引用,因此在使用线程池的应用程序服务器中使用 s 时,最终可能会出现类加载泄漏。您需要非常小心地清理任何 s 你或使用 的方法。ThreadLocalThreadThreadLocalThreadLocalget()set()ThreadLocalremove()

如果在完成后不进行清理,则它对作为已部署 Web 应用的一部分加载的类的任何引用都将保留在永久堆中,并且永远不会被垃圾回收。重新部署/取消部署 web 应用不会清理对 web 应用类的每个引用,因为 web 应用不是 Web 应用拥有的东西。每个后续部署都将创建该类的一个新实例,该实例永远不会被垃圾回收。ThreadThread

由于一些谷歌搜索,您最终将遇到内存不足的异常,并且可能会在一些谷歌搜索之后增加而不是修复错误。java.lang.OutOfMemoryError: PermGen space-XX:MaxPermSize

如果您最终遇到这些问题,您可以使用Eclipse的内存分析器和/或遵循Frank Kieviet的指南后续操作来确定哪个线程和类保留了这些引用。

更新:重新发现Alex Vasseur的博客文章,帮助我追踪我遇到的一些问题。ThreadLocal


推荐