本文正在参加「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 可以有效的使你的代码整洁,但是记得在你用完后清理掉, 反面例子