转载请注明出处:
1. 先展示threadLocal的一个简单封装,该封装用来在不同的请求线程中解析用户参数。在请求经过过滤器时,
对用户的信息进行设置入 ThreadLocalContext 中,可在同一个请求的不同业务中获取用户的信息参数。
import com.homepage.UserInfo;
public class ThreadLocalContext {
private static ThreadLocal<UserInfo> userThreadLocal = new ThreadLocal<>();
public static UserInfo getThreadLocalContext(){
UserInfo user = userThreadLocal.get();
if (user == null){
return new UserInfo();
}
return user;
}
public static void setUserThreadLocal(UserInfo user){
userThreadLocal.set(user);
}
public static void clear(){
userThreadLocal.remove();
}
}
以上为ThreadLocal的一个简单封装。
2. 使用的场景主要为:
- 每个线程需要有自己单独的实例
- 实例需要在多个方法中共享,但不希望被多线程共享
3.原理:
每个运行的线程都会有一个类型为ThreadLocal.ThreadLocalMap的map,这个map就是用来存储与这个线程绑定的变量,
map的key就是ThreadLocal对象,value就是线程正在执行的任务中的某个变量的包装类Entry。可以通过set方法来看threadLocal实现的原理:
/**
* Sets the current thread's copy of this thread-local variable
* to the specified value. Most subclasses will have no need to
* override this method, relying solely on the {@link #initialValue}
* method to set the values of thread-locals.
*
* @param value the value to be stored in the current thread's copy of
* this thread-local.
*/
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
4.ThreadLocal作用:
在多线程程序中,同一个线程在某个时间段只能处理一个任务.我们希望在这个时间段内,任务的某些变量能够和处理它的线程进行绑定,
在任务需要使用这个变量的时候,这个变量能够方便的从线程中取出来.ThreadLocal能很好的满足这个需求,用ThreadLocal变量的程序看起来
也会简洁很多,因为减少了变量在程序中的传递。
5. 为什么ThreadLocalMap的Entry是一个weakReference?
使用weakReference,能够在ThreadLocal失去强引用的时候,ThreadLocal对应的Entry能够在下次gc时被回收,回收后的空间能够得到复用,
在一定程度下能够避免内存泄露.
6. 使用ThreadLocal应该注意什么?
在使用ThreadLocal对象,尽量使用static,不然会使线程的ThreadLocalMap产生太多Entry,从而造成内存泄露
7.使用threadLocal 如何避免内存泄露:
在 threadLocal 中的变量在线程结束之前清空 当前 threadLocal 中的变量。或是在threadLocal中变量使用结束时,手动清除 threadLocal 的变量
ThreadLocalContext.clear() 方法或
ThreadLocalContext.set(null);