【问题标题】:How to clean ThreadLocal's data when the Thread's task is doneThread的任务完成后如何清理ThreadLocal的数据
【发布时间】:2013-11-23 13:11:21
【问题描述】:

我有这三个问题:

1.Is there a way to clean ThreadLocal's data when the Thread's task is done.
2.How about when the thread is in ThreadPool.
3.How can I know a Thread is reused and given back to the ThreadPool.

【问题讨论】:

  • 你指的是什么线程池?这些? docs.oracle.com/javase/tutorial/essential/concurrency/…
  • @isnot2bad 我不知道它是什么线程池。它只是一个池保存线程。
  • 我的意思是,你是使用 JDK 的线程池,还是使用任何其他第三方库?
  • @isnot2bad 这不是一个特定的池。可能来自 JDK 或其他第三方库。

标签: java multithreading threadpool


【解决方案1】:

广告 1) 要“清理”ThreadLocal 的数据,只需调用 ThreadLocal#remove()

广告 2) 如果Thread 从线程池中访问,ThreadLocals 的行为不会有所不同。

广告 3) 你不能。它高度依赖于您使用的线程池。一些线程池提供了一种挂钩方式,而另一些则没有。

旁注:如果线程池的Thread 是新创建或重用或归还的,通常不应该有任何意义,除非您想扩展现有线程池。

【讨论】:

  • 我有一个基于 thred 的方法缓存。我想在当前线程的任务完成后清理缓存。
  • 然后在任务结束时将其移除!
  • 我不想在每个任务中编写代码,有没有办法自动执行此操作?喜欢 AOP?
  • 当然。哎呀! ;) 您还可以使用包装任务,在执行实际任务之前进行准备,并在执行实际任务之后进行清理。
  • 您可以覆盖afterTask()beforeTask() 方法。
【解决方案2】:

从线程池中删除线程局部变量在应用程序容器中得到了广泛应用。我在这里回答了一个关于这个主题的问题:Why do some webservers complain about memory leaks they create?

摆脱线程局部变量的最简单方法是摆脱持有它们的胎面。清除这些变量的唯一其他方法是反射性地访问线程的 thread local map,它基本上表示一个映射,其中线程 id 指向值,这是实现线程本地指针的方式。使用线程本地时不涉及 JVM 魔法。最后它只是一张可以清除的地图。 (在链接的文章中,我解释了为什么在共享线程时这通常是一个坏主意。)然而,反射访问会比更新线程更昂贵。

但是,您可能会重新考虑您的设计。 Guava 提供了一个可以使用软引用构建的缓存。这样,您可以构建一个适当的缓存,您的密钥可以由线程特定的 UUID 组成。我不太了解您的申请,无法在这里给您进一步的建议。不过,使用线程局部变量几乎总是错误的。

【讨论】:

    【解决方案3】:

    有没有办法在 Thread 的任务完成时清理 ThreadLocal 的数据。

    您可以在任务代码中显式设置 null。

    线程在ThreadPool中的时候怎么样。

    同 1。

    我如何知道线程被重用并返回给线程池。

    您也可以为此使用 ThreadLocal。但是您不需要区分新线程和重用线程。

    【讨论】:

      猜你喜欢
      • 2019-05-17
      • 1970-01-01
      • 1970-01-01
      • 2018-06-24
      • 2012-10-20
      • 1970-01-01
      • 1970-01-01
      • 2018-12-01
      • 1970-01-01
      相关资源
      最近更新 更多