2013-07-26 140 views
0

从线程池中重用Thread时,我们从线程的上次执行中获取线程局部变量值。返回ThreadPool时清除ThreadLocal值

我知道Thread本地是Thread的一部分,因此当我们使用Thread pool时它被重用。但我的问题是我不想在最后一次执行中使用线程局部变量(许多人使用有效的用例)。

当线程在当前执行后进入池时,有没有更好的清除线程局部值的方法?

+0

你能告诉我们你的代码吗? – tbodt

+0

为什么不在从池中请求线程实例时重置线程池变量? – Trinimon

+2

不清除'ThreadLocal'值是Java中内存泄漏的典型例子之一。我建议你用某种拦截器模式包装你的操作,并在完成后清除它的价值。你在使用'ExectuorService'吗? –

回答

1

您可以使用反射来清除线程的线程本地映射。这将清除所有线程本地人,无论他们在哪里。

理想情况下,您应该编写代码,以便您的线程本地语言不像这样有状态。这意味着单元测试更加困难。

1

清除ThreadLocal应该是“线程用户”的责任 - 也就是说,放置ThreadLocal的代码也应该清除它。使用例如一个try-finally-block来确保发生这种情况。

但是,你可以破解你想要的!说真的,这并不困难 - 您只需要反思自己进入Thread对象/类的方式,找到ThreadLocals所在的Map并清除它。

2

无法使用公共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; 
    ...