该什么时候使用ThreadLocal变量,它是如何工作的

原文 标签 IT工具网 java

回答1

一种可能的(也是常见的)使用情形是你不想通过同步方式(synchronized)访问非线程安全的对象(说的就是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

因为ThreadLocal是一个既定线程内部的数据引用,你可能在使用线程池的应用服务器上因此引起类加载时候的内存泄漏。你需要使用remove()方法很小心地清理TheadLocal中get()或者set()的变量。 如果程序执行完毕没有清理的话,它持有的任何对类的引用将作为部署的Web应用程序的一部分仍保持在永久堆,永远无法得到回收。重新部署/取消部署也无法清理对应用程序类的引用,因为线程不是被你的应用程序所拥有的。 每次成功部署都会创建一个永远不会被垃圾回收类的实例。

最后将会遇到内存不足的异常-java.lang.java.lang.OutOfMemoryError: PermGen space -XX:MaxPermSize,在google了很多答案之后你可能只是增加了-XX:MaxPermSize,而不是修复这个bug。 倘若你的确遇到这种问题,可以通过Eclipse’s Memory Analyzer或根据Frank Kieviet’s guidefollowup来判断哪些线程和类保留了那些引用。

更新:又发现了Alex Vasseur’s blog entry,它帮助我查清楚了一些ThreadLocal的问题。

stackoverflow链接:http://stackoverflow.com/questions/817856/when-and-how-should-i-use-a-threadlocal-variable

相关文章:

Android中"UserManger.isUserAGoat()"的合适案例

为Eclipse自动代码格式化设置行的最大长度?

HashMap和Hashtable的区别

java如何创建单例

java - 这是我应该停止Java中的线程的方式吗?

java - android:在非 Activity 类中使用 openOrCreateDatabase

JavaScript中的事件委托(delegate)

java.lang.NoClassDefFoundError : com. google.gson.stream.JsonReader 在使用 Amazon S3 上传图像时在 android 中的 Pre-Lollipop 上出错

java - 从 MainActivity 中的 onCreate() 启动另一个 Activity?

java - 如何为这个类编写一个junit测试用例