ThreadLocal,线程本地变量,也有些地方叫做线程本地存储。ThreadLocal为变量在每个线程中都创建了一个副本,每个线程可以访问自己内部的副本变量。
ThreadLocal类提供了以下四个方法:
public T get() { }
public void set(T value) { }
public void remove() { }
protected T initialValue() { }
get()方法是用来获取ThreadLocal在当前线程中保存的变量副本,set()用来设置当前线程中变量的副本,remove()用来移除当前线程中变量的副本,initialValue()是一个protected方法,一般是用来在使用时进行重写的,它是一个延迟加载方法,
在每个线程Thread内部有一个ThreadLocal.ThreadLocalMap类型的成员变量threadLocals,这个threadLocals就是用来存储实际的变量副本的,键值为当前ThreadLocal变量,value为变量副本(即T类型的变量)。初始时,在Thread里面,threadLocals为空,当通过ThreadLocal变量调用get()方法或者set()方法,就会对Thread类中的threadLocals进行初始化,并且以当前ThreadLocal变量为键值,以ThreadLocal要保存的副本变量为value,存到threadLocals。在进行get之前,必须先set,否则会报空指针异常;如果想在get之前不需要调用set就能正常访问的话,必须重写initialValue()方法。最常见的ThreadLocal使用场景为 用来解决 数据库连接、Session管理等。
private static ThreadLocal<Connection> connectionHolder= new ThreadLocal<Connection>() {
public Connection initialValue() {
return DriverManager.getConnection(DB_URL);
} };
public static Connection getConnection() {
return connectionHolder.get();
}
下面例二:
public static void setHolder(FutureHolder holder) throws IllegalStateException {
FutureHolder old = futureHolder.get();
if(old != null) { throw new IllegalStateException("cannot repeat init"); } futureHolder.set(holder); }
使用的时候直接调用类名.方法名返回一个对象然后直接操作,保存的时候调用类中的方法存贮在ThreadLocal中。
下面例三:
public abstract class WebSocketContextHolder {
private static final ThreadLocal<WebSocketRequestAttributes> requestAttributesHolder =
new NamedThreadLocal<WebSocketRequestAttributes>("WebSocket Request attributes");
/**
* 获取当前的 WebSocketRequestAttributes,线程局部存储中如果没有, 抛出异常
* @return
* @throws IllegalStateException
*/
public static WebSocketRequestAttributes currentRequestAttributes() throws IllegalStateException {
WebSocketRequestAttributes attributes = getRequestAttributes();
if(attributes == null) {
throw new IllegalStateException("no websocket attribute");
}
return attributes;
}
/**
* 获取当前的 WebSocketRequestAttributes,线程局部存储中如果没有, 返回 null
* @return WebSocketRequestAttributes
*/
public static WebSocketRequestAttributes getRequestAttributes() {
return requestAttributesHolder.get();
}
/**
* 设置 WebSocketRequestAttributes, 放到线程局部存储中,如果已经有,抛出异常
* @param attributes
* @throws IllegalStateException
*/
public static void setRequestAttributes(WebSocketRequestAttributes attributes) throws IllegalStateException {
WebSocketRequestAttributes old = requestAttributesHolder.get();
if(old != null)
throw new IllegalStateException("cannot repeat init");
requestAttributesHolder.set(attributes);
}
/**
* 清理线程局部存储中数据
*/
public static void clearRequestAttributes() {
requestAttributesHolder.remove();
}
/**
* 帮助清理 WebSocketRequestAttributes
* @param attributes
*/
public static void clean(WebSocketRequestAttributes attributes) {
attributes.clearAll();
}
}