ThreadLocal简介
在单线程的程序里,可以通过static
变量或者singleton对象的方式定义全局的、共享的变量。
在多线程的程序里,如果想定义在一个线程内部共享的变量,可以考虑使用ThreadLocal
。
ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread
一般来说,ThreadLocal
对象会被声明成类的私有静态成员,比如下面这个例子来自ThreadLocal的javadoc,
public class ThreadId {
// Atomic integer containing the next thread ID to be assigned
private static final AtomicInteger nextId = new AtomicInteger(0);
// Thread local variable containing each thread's ID
private static final ThreadLocal<Integer> threadId =
new ThreadLocal<Integer>() {
@Override protected Integer initialValue() {
// 让不同的线程有不同的初始值
return nextId.getAndIncrement();
}
};
// 不同的线程调用threadId.get()会返回不同的值,每个线程都有其各种的拷贝
public static int get() {
return threadId.get();
}
}
ThreadLocal的实现
每个线程对应的Thread对象里存在着一个map(所以不同线程的map相互隔离,没有竞争),
// 摘自Thread类的定义
ThreadLocal.ThreadLocalMap threadLocals = null;
ThreadLocalMap的实现是一个hash表,定义如下,
static class ThreadLocalMap {
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
// ThreadLocal对象关联的对象
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
private Entry[] table;
}
map中的key由ThreadLocal对象们担当,value则是ThreadLocal对象所关联的对象。
下面是ThreadLocal::get()
的伪代码(真实的实现考虑了threadLocals
的lazy initialization),
public class ThreadLocal<T> {
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap.Entry e = t.threadLocals.get(this);
if (e == null) {
t.threadLocals.set(this, this.initialValue());
}
return (T)e.value;
}
}
ThreadLocal和内存泄漏
...