从线程池中重用Thread时,我们从线程的上次执行中获取线程局部变量值。返回ThreadPool时清除ThreadLocal值
我知道Thread本地是Thread的一部分,因此当我们使用Thread pool时它被重用。但我的问题是我不想在最后一次执行中使用线程局部变量(许多人使用有效的用例)。
当线程在当前执行后进入池时,有没有更好的清除线程局部值的方法?
从线程池中重用Thread时,我们从线程的上次执行中获取线程局部变量值。返回ThreadPool时清除ThreadLocal值
我知道Thread本地是Thread的一部分,因此当我们使用Thread pool时它被重用。但我的问题是我不想在最后一次执行中使用线程局部变量(许多人使用有效的用例)。
当线程在当前执行后进入池时,有没有更好的清除线程局部值的方法?
您可以使用反射来清除线程的线程本地映射。这将清除所有线程本地人,无论他们在哪里。
理想情况下,您应该编写代码,以便您的线程本地语言不像这样有状态。这意味着单元测试更加困难。
清除ThreadLocal应该是“线程用户”的责任 - 也就是说,放置ThreadLocal的代码也应该清除它。使用例如一个try-finally-block来确保发生这种情况。
但是,你可以破解你想要的!说真的,这并不困难 - 您只需要反思自己进入Thread对象/类的方式,找到ThreadLocals所在的Map并清除它。
无法使用公共API清除ThreadLocals。尽管如此,ThreadPoolExecutor有一个hook方法,我们可以在执行之前使用反射清除Thread中的ThreadLocals
public class ThreadPoolExector
protected void beforeExecute(Thread t, Runnable r) {
... set t.threadLocals and t.inheritableThreadLocals fields to null using reflection
}
...
public class Thread
...
ThreadLocal.ThreadLocalMap threadLocals;
ThreadLocal.ThreadLocalMap inheritableThreadLocals;
...
你能告诉我们你的代码吗? – tbodt
为什么不在从池中请求线程实例时重置线程池变量? – Trinimon
不清除'ThreadLocal'值是Java中内存泄漏的典型例子之一。我建议你用某种拦截器模式包装你的操作,并在完成后清除它的价值。你在使用'ExectuorService'吗? –