2011-09-13 30 views
7

我有一个关于java和并发性的问题。Java缓存线程池和线程本地

假设我有一个称为a的ThreadLocal变量。我使用CachedThreadPool获取新线程。 当一个线程被重新调用时,ThreadLocal变量会发生什么?它保持相同的值(因为它是一个相同的线程),或者它开始为空(就像线程是新的一样)?

感谢

回答

10

默认情况下,ThreadLocals与线程一起重复使用。如果你需要他们重新初始化,您可以通过以下重写提到的方法,这样做:

from javadoc for java.util.concurrent.ThreadPoolExecutor

挂钩方法 这个类提供保护重写beforeExecute(java.lang.Thread中,JAVA。 lang.Runnable)和afterExecute(java.lang.Runnable,java.lang.Throwable)在每个任务执行前后调用的方法。这些可以用来操纵执行环境;例如,重新初始化ThreadLocals,收集统计信息或添加日志条目。此外,可以覆盖方法terminate()以执行Executor完全终止后需要执行的任何特殊处理。 如果挂钩或回调方法抛出异常,则内部工作线程可能会失败并突然终止。

+1

我在这里看到的一个可解决的问题是,ThreadPoolExecutor需要知道线程本地人。有点分离。可以通过一个线程完成执行后抛出事件的observable来解决。一个特定的线程本地可以注册(观察者)一旦afterExecute事件被激发,做一个清理。 –

3

如果线程返回到池中,ThreadLocal的变量仍然会被连接到它。当使用带池的ThreadLocals时,必须注意能够设置何时将线程从池中拉出并在返回之前解除设置。

2

您可以使用反射来清除线程的线程本地池。你可以做

public static void clearAllThreadLocals() { 
    try { 
     Field threadLocals = Thread.class.getDeclaredField("threadLocals"); 
     threadLocals.setAccessible(true); 
     threadLocals.set(Thread.currentThread(), null); 
    } catch (Exception e) { 
     throw new AssertionError(e); 
    } 
}