ThreadLocal 本地线程变量的使用场景| Java Debug 笔记

448 阅读2分钟

本文正在参加「Java主题月 - Java Debug笔记活动」,详情查看

ThreadLocal 本地线程变量的使用场景,原文链接

问题

ThreadLocal 本地线程变量,什么时候用?应该怎么用?

答案1

第一种常见的使用场景,使用线程不安全的对象时,想不用 synchronizing 同步块也能保证多线程互不影响的使用(例如: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);
    }
}

ThreadLocal 官方文档

答案2

ThreadLocal 是线程中指定数据的引用,因此在使用应用服务的线程池时,要小心内存泄露,一定要记得在使用完后进行清理,清理使用 ThreadLocal 的 remove 方法。 如果用完后不清除,它将会一直被类加载器部署在永久代中(permanent heap),因为还有引用关系,所以不会被 GC 回收。

程序最终可能会抛出一个异常 java.lang.OutOfMemoryError: PermGen space,如果你只是百度的话,答案都是 -XX:MaxPermSize,并未解决根本问题。

答案3

许多框架使用 ThreadLocal 来维护当前线程的上下文内容,例如把当前事务存储在 ThreadLocal ,这样你后面使用的时候就无需作为方法参数进行传递了,可以直接在 ThreadLocal 中获取。Web 应用会存储请求、会话的信息在 ThreadLocal,这样你的应用就可以很容易获取它。

ThreadLocal 是一种全局变量(尽管它被限制在本地线程中),请小心使用,避免内存泄露。在你设计 API 时,ThreadLocal 可以有效的使你的代码整洁,但是记得在你用完后清理掉, 反面例子