线程本地删除?

2022-09-02 00:42:18

当使用时,我应该总是在我完成时调用,或者当我做旧值被替换时,所以是多余的吗?ThreadLocalremove()setremove


答案 1

因为 has of 和 ,现在如果你不删除使用它的线程中的值,那么它将创建内存泄漏。ThreadLocalMapcurrentThreadvalue

您应该始终调用 remove,因为 ThreadLocal 类从 ThreadLocal 定义的 Thread 类中放置值。值 localValues; 这也将导致保存线程和关联对象的引用。

从源代码ThreadLocal

该值将设置为 null,并且基础条目仍将存在。


答案 2

set始终替换旧值。

对于

  • Calendar.set() 和 Date.set()
  • BitSet.set()
  • List.set()
  • 制定

你的意思是没有删除它不会被GCed?

在螺纹死亡之前,它不会被移除。它不会在你身上消失,除非你调用 remove()

这是否是内存泄漏取决于您的程序。您必须创建许多具有大型线程本地对象的线程,由于某种原因,您不需要这些线程。例如,1000个线程和一个1 KB的对象可能会浪费高达1 MB,但如果你正在做这种事情,这表明存在设计问题。


您可能遇到内存泄漏的唯一位置是。

for (int i = 0; ; i++) {
    // don't subclass Thread.
    new Thread() {
        // this is somewhat pointless as you are defining a ThreadLocal per thread.
        final ThreadLocal<Object> tlObject = new ThreadLocal<Object>() {
        };

        public void run() {
            tlObject.set(new byte[8 * 1024 * 1024]);
        }
    }.start();
    Thread.sleep(1);
    if (i % 1000 == 0) {
        System.gc();
        System.out.println(i);
    }
}

与印刷品。-verbosegc

[Full GC 213548K->49484K(3832192K), 0.0334194 secs]
39000
[GC 2786060K->82412K(3836864K), 0.0132035 secs]
[GC 2815569K->107052K(3836544K), 0.0212252 secs]
[GC 2836162K->131628K(3837824K), 0.0199268 secs]
[GC 2867613K->156204K(3837568K), 0.0209828 secs]
[GC 2886894K->180780K(3838272K), 0.0191244 secs]
[GC 2911942K->205356K(3838080K), 0.0187482 secs]
[GC 421535K->229932K(3838208K), 0.0192605 secs]
[Full GC 229932K->49484K(3838208K), 0.0344509 secs]
40000

注意:完整GC后的大小相同49484K

在上面的例子中,你将有一个ThreadLocal,它指的是ThreadLocal的Thread。但是,由于线程已失效,它不会导致内存泄漏,因为它成为一个关注对象,即当A ->B和B ->A时

我在循环中运行了上面的示例几分钟,GC级别移动了很多,但最小大小仍然很小。