ThreadLocal
ThreadLocal类的定义
public class ThreadLocal<T> extends Object
官方文档说明如下:
This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable. ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).
大致意思是:ThreadLocal提供“线程本地变量”,ThreadLocal为每个使用该变量的线程提供独立的变量副本,每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
方法说明
ThreadLocal类很简单,只有4个方法,如下:
Modifier and Type | Method | Description |
---|---|---|
T | get() | 返回当前线程所对应的线程局部变量 |
protected T | initialValue() | 返回该线程局部变量的初始值,缺省实现直接返回一个null。这个方法是一个延迟调用方法,在线程第1次调用get()或set(Object)时才执行,并且仅执行1次。 |
void | remove() | 删除当前线程局部变量的值 |
void | set(T value) | 设置当前线程的线程局部变量的值 |
通过ThreadLocal的“thread-local variables”特性,我们可以很方便的实现为每个线程分配一个资源,代码如下:
class ResourceManager{
private static volatile ResourceManager mgr;
private final AtomicInteger nextId = new AtomicInteger(0);
private ThreadLocal<String> threadLocal = new ThreadLocal<String>(){ //保存所有资源
protected String initialValue() {
return "Resource_"+nextId.incrementAndGet();
};
};
private ResourceManager(){
}
public static ResourceManager getMgr(){
if(mgr==null){
synchronized(ResourceManager.class){
if(mgr==null){
mgr = new ResourceManager();
}
}
}
return mgr;
}
public String getResource(){
return threadLocal.get();
}
}
在调用threadLocal.get方法的时候会触发initialValue方法,注意initialValue只会执行一次。
thread-local variable 生命周期
Each thread holds an implicit reference to its copy of a thread-local variable as long as the thread is alive and the ThreadLocal instance is accessible; after a thread goes away, all of its copies of thread-local instances are subject to garbage collection (unless other references to these copies exist).
总结
ThreadLocal和线程同步机制(synchronized、lock)都可以保证线程安全,但二者实现上有着本质不同。
在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。
而ThreadLocal则通过为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。
参考资料:
http://docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html