转载请注明出处:

  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);