一、什么是ThreadLocal
- java.lang包下的一个类;
- 当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本;
public class PostContextUtils {
/**
* 确保线程安全
*/
static ThreadLocal<PostServerContext> dataThreadLocal = new ThreadLocal<PostServerContext>();
...
}
ThreadLocal类的方法
- public void set(T value); 设置当前线程的线程局部变量值
- public T get(); 返回当前线程所对应的线程局部变量值
- public void remove(); 删除前线程局部变量值,目的是为了减少内存的占用(TODO:线程池,线程并未真正被销毁,防止数据混淆)
- protected Object initialValue(); 为了让子类覆盖而设计,缺省返回null值
二、实现原理
- 在ThreadLocal类中有一个ThreadLocalMap,用于存储每一个线程的变量副本,key为当前线程对象,value为对应线程的变量副本。
- 理解ThreadLocalMap类
public class ThreadLocal<T> {
...
static class ThreadLocalMap {
/**
* The entries in this hash map extend WeakReference, using
* its main ref field as the key (which is always a
* ThreadLocal object). Note that null keys (i.e. entry.get()
* == null) mean that the key is no longer referenced, so the
* entry can be expunged from table. Such entries are referred to
* as "stale entries" in the code that follows.
*/
static class Entry extends WeakReference<ThreadLocal> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal k, Object v) {
super(k);
value = v;
}
}
}
}
public class Thread implements Runnable {
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class.
*/
ThreadLocal.ThreadLocalMap threadLocals = null;
}
ThreadLocalMap是ThreadLocal类的一个静态内部类,它实现了键值对的设置和获取;
每个线程中都有一个独立的ThreadLocalMap私有对象,它所存储的值,只能被当前线程读取和修改;
ThreadLocal类通过操作每一个线程特有的ThreadLocalMap对象,从而实现了变量访问在不同线程中的隔离;
- ThreadLocalMap中的key是当前线程对象吗?
public class PostLogUtil {
//用于保存一次请求的id,一次请求使用同一个id
static ThreadLocal<Long> logInfoThreadLocal =new ThreadLocal<Long>();
...
}
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;
}
return setInitialValue();
}
三、拓展
与同步机制比较
同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。
与私有变量比较
避免参数传递,方便对象访问。