【问题标题】:Will the ThreadLocal object be cleared after thread returned to Thread Pool?线程返回线程池后,ThreadLocal对象会被清除吗?
【发布时间】:2015-07-31 10:43:57
【问题描述】:

执行期间存储在ThreadLocal 存储中的内容是否会在线程返回到 ThreadPool 时自动清除(如预期的那样)??

在我的应用程序中,我在某些执行期间将一些数据放入ThreadLocal,但如果下次使用相同的线程,那么我会在ThreadLocal 存储中找到过时的数据。

【问题讨论】:

  • 你不是在回答你自己的问题吗?您说:“如果正在使用相同的线程,那么我正在寻找过时的数据”。那么,你的问题是什么?

标签: java multithreading threadpool thread-local


【解决方案1】:

不,ThreadLocal 对象与线程而非任务相关联。因此 ThreadLocal 应与线程池一起谨慎使用。作为一个原则,只有当线程本地生命周期与任务的生命周期一致时,线程本地才对线程池有意义

【讨论】:

    【解决方案2】:

    线程返回到ThreadPool时是否会自动清除线程执行过程中保存在ThreadLocal存储中的内容

    没有。 ThreadLocals 与 Threads 相关联, 与传递给线程池任务队列的 Callable/Runnable 的执行相关联。除非明确清除 - @PeterLawrey 给出了一个关于如何执行此操作的示例 - ThreadLocals 及其状态通过多个任务执行持续存在。

    听起来您可以使用在 Callable/Runnable 中声明的局部变量来实现所需的行为

    【讨论】:

      【解决方案3】:

      没有。作为一个原则,谁把东西放在线程本地应该负责清除它

      threadLocal.set(...);
      try {
        ...
      } finally {
        threadLocal.remove();
      }
      

      【讨论】:

        【解决方案4】:

        除非您这样做,否则 ThreadLocal 和 ThreadPool 不会相互交互。

        你可以做的是一个单一的 ThreadLocal,它存储你想要保持的所有状态,并在任务完成时重置它。您可以覆盖 ThreadPoolExecutor.afterExecute(或 beforeExecute)来清除您的 ThreadLocal(s)

        来自线程池执行器

        /**
         * Method invoked upon completion of execution of the given Runnable.
         * This method is invoked by the thread that executed the task. If
         * non-null, the Throwable is the uncaught {@code RuntimeException}
         * or {@code Error} that caused execution to terminate abruptly.
         *
         * <p>This implementation does nothing, but may be customized in
         * subclasses. Note: To properly nest multiple overridings, subclasses
         * should generally invoke {@code super.afterExecute} at the
         * beginning of this method.
         *
        ... some deleted ...
         *
         * @param r the runnable that has completed
         * @param t the exception that caused termination, or null if
         * execution completed normally
         */
        protected void afterExecute(Runnable r, Throwable t) { }
        

        您可以一次清除所有线程,而不是跟踪所有 ThreadLocals。

        protected void afterExecute(Runnable r, Throwable t) { 
            // you need to set this field via reflection.
            Thread.currentThread().threadLocals = null;
        }
        

        【讨论】:

        • dude... 如果ThreadPoolExecutor 使用一些线程局部变量会怎样。
        • 在企业环境中通过反射设置(包)受保护的字段是非法的安全漏洞! :(
        • @MGM 仅仅因为你可以做某事,并不意味着你应该做。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-10
        • 1970-01-01
        • 1970-01-01
        • 2012-10-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多