什么时候应该使用ThreadLocal变量?
如何使用?
一种可能的(并且是常见的)用法是,当你有一些不是线程安全的对象,但又希望避免同步对该对象的访问时(我正在看着你,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); } }
由于a ThreadLocal是对给定数据的引用,因此在使用线程池的应用程序服务器中使用s Thread时,可能会导致类加载泄漏ThreadLocal。你需要非常小心,以清理ThreadLocal你的所有内容get()或set()使用ThreadLocal的remove()方法。
a ThreadLocal
s Thread
ThreadLocal
get()
set()
hreadLocal
remove()
如果完成后不清理,则它对作为部署的Webapp的一部分加载的类的任何引用将保留在永久堆中,并且永远不会收集垃圾。重新部署/取消部署Web应用程序不会清除每个Thread对Web应用程序类的引用,因为ThreadWeb应用程序不是你的Web应用程序所拥有的。每次后续部署都将创建该类的新实例,该实例将永远不会被垃圾回收。
ThreadWeb
由于java.lang.OutOfMemoryError: PermGen space出现一些谷歌搜索之后,你可能最终会遇到内存不足异常,而这只会增加-XX:MaxPermSize而不是修复该错误。
java.lang.OutOfMemoryError: PermGen space
-XX:MaxPermSize
如果你确实遇到了这些问题,则可以使用Eclipse的Memory Analyzer和/或遵循Frank Kieviet的指南和后续步骤,确定哪个线程和类保留了这些引用。
Eclipse
Memory Analyzer
Frank Kieviet