在重用线程池中的线程时,我们从线程的最后一次执行中获取线程局部变量值。
我知道 Thread local 是 Thread 的一部分,所以当我们使用线程池时它会被重用。但我的问题是我不想在最后一次执行中使用线程局部变量集(对很多人来说都是有效的用例)。
当线程在当前执行后进入池时,有没有更好的方法来清除线程本地值?
在重用线程池中的线程时,我们从线程的最后一次执行中获取线程局部变量值。
我知道 Thread local 是 Thread 的一部分,所以当我们使用线程池时它会被重用。但我的问题是我不想在最后一次执行中使用线程局部变量集(对很多人来说都是有效的用例)。
当线程在当前执行后进入池时,有没有更好的方法来清除线程本地值?
无法使用公共 API 清除 ThreadLocals。尽管如此,ThreadPoolExecutor 有一个钩子方法,我们可以在执行前使用反射清除 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;
...
您可以使用反射清除线程的线程本地映射。这将清除所有线程本地变量,无论它们在哪里。
理想情况下,您应该编写代码,这样您的线程本地变量就不会像这样有状态。这意味着单元测试更加困难。
清除 ThreadLocal 应该是“线程用户”的责任——也就是说,放置 ThreadLocal 的代码也应该清除它。使用例如 try-finally-block 来确保发生这种情况。
但是,您可以破解您想要的内容!说真的,这并不难——你只需反省进入 Thread 对象/类的方式,找到 ThreadLocals 所在的 Map,然后清除它。