threadlocal用法及原理

用一个简单的java web实例来说明:

UserSessionFilter.java 过滤器

HttpSession httpsession = ((HttpServletRequest)req).getSession();

private static ThreadLocal<HttpSession> session = new ThreadLocal<HttpSession>();

UserSessionFilter.session.set(httpsession); >>>  本类中的session初始值为HttpSession


Object userSession = httpsession.getAttribute("user");  >>> 从HttpSession中取得"user"的值

ThreadLocalUserSession.set(userSession);   >>> 将从HttpSession中取得"user"的值设置到ThreadLocal中


Map<String, Object> map = (Map<String, Object>)session.getAttribute("vars");  取HttpSession中的"vars"并设置到ThreadLocalUserSession类中
ThreadLocalUserSession.setVars(map);


UserSessionUtil.java 工具类

设置session:

1.

UserSessionFilter.getHttpSession().setAttribute("user", userSession); >>> 本质是往HttpSession中设置

ThreadLocalUserSession.set(userSession);  >>> 本质是往ThreadLocal中设置

2.

UserSessionFilter.getHttpSession().setAttribute("vars", vars); >>> 本质是往HttpSession中设置
ThreadLocalUserSession.setVars(vars);  >>> 本质是往ThreadLocal中设置


取值session:

ThreadLocal.get(); >>> 本质是从ThreadLocal中取值


====================================

web.xml:

<filter>
       <filter-name>UserSessionFilter</filter-name>
       <filter-class>com.licaike.framework.server.filter.UserSessionFilter</filter-class>
</filter>
<filter-mapping>
      <filter-name>UserSessionFilter</filter-name>
      <url-pattern>/*</url-pattern>
</filter-mapping>


UserSessionFilter.java:

public class UserSessionFilter implements Filter{
    private static ThreadLocal<HttpSession> session = new ThreadLocal<HttpSession>();
    
    public void destroy() {
    }
    
    public static HttpSession getHttpSession(){
        return UserSessionFilter.session.get();
    }
    
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain) throws IOException, ServletException {
        // 仅仅是记录下WEB session
        HttpSession session = ((HttpServletRequest)req).getSession();
        UserSessionFilter.session.set(session);
      

        //设置用户身份信息
        Object userSession = session.getAttribute("user");
        ThreadLocalUserSession.set(userSession);

        // 设置session变量
        Map<String, Object> map = (Map<String, Object>)session.getAttribute("vars");
        if(map == null){
            map = new HashMap<String,Object>();
        }
        ThreadLocalUserSession.setVars(map);
        filterChain.doFilter(req, res);
    }

    public void init(FilterConfig arg0) throws ServletException {
    }

}


UserSessionUtil.java:

public class UserSessionUtil {
    public static UserSession get(){
        return (UserSession)ThreadLocalUserSession.get();
    }
    
    //调用此方法真正写入到session
    public static void set(UserSession userSession){
        UserSessionFilter.getHttpSession().setAttribute("user", userSession);  //过滤器里设到本地线程变量里
        ThreadLocalUserSession.set(userSession);  //此处设到本地线程变量里
    }
    
    public static Map<String,Object> getVars(){
        return ThreadLocalUserSession.getVars();
    }
    
    public static void setVars(Map<String,Object> vars){
        UserSessionFilter.getHttpSession().setAttribute("vars", vars);  //过滤器里设到本地线程变量里
        ThreadLocalUserSession.setVars(vars); //此处设到本地线程变量里
    }
    
    public static void initSession(){
        //初始化userSession
        if(get()==null) set(new UserSession());
        //初始化其他
        if(getVars()==null) setVars(new HashMap<String,Object>());
    }
}


ThreadLocalUserSession.java:

public class ThreadLocalUserSession implements Serializable{
    private static ThreadLocal<Object> threadLocalUserSession = new ThreadLocal<Object>() ;
    private static ThreadLocal<Map<String,Object>> vars = new ThreadLocal<Map<String,Object>>() ;
    
    public static void set(Object object){
        threadLocalUserSession.set(object);
    }
    public static Object get(){
        Object object = threadLocalUserSession.get();
        return object;
    }

    public static void setVars(Map<String,Object> vars){
        ThreadLocalUserSession.vars.set(vars);
    }
    public static Map<String,Object> getVars(){
        Map<String,Object> map = vars.get();
        return map;
    }

    private static final long serialVersionUID = 4343534534354L;
}


====================================

关于Theadlocal的说明:

进入Theadlocal代码,可以发现如下的片段:

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确实只有一个变量,但是它内部包含一个map,针对每个thread保留一个entry。









ThreadLocal是Java中的一个线程级别的变量,它提供了一种简单的方式来在多线程环境中维护变量的值。每个线程都拥有自己独立的ThreadLocal实例,并且可以通过该实例来获取和设置其对应的变量的值。 ThreadLocal原理是通过在每个线程中创建一个独立的副本来存储变量的值。这样,每个线程都可以独立地访问和修改自己的副本,而不会对其他线程产生影响。 ThreadLocal的使用非常简单。首先,我们需要创建一个ThreadLocal对象,并指定要存储的变量类型。然后,我们可以通过调用ThreadLocal的get方法来获取当前线程中与该ThreadLocal对象关联的变量值,如果当前线程还没有设置过该变量,get方法会返回null。类似地,我们可以通过调用ThreadLocal的set方法来设置当前线程中与该ThreadLocal对象关联的变量值。 下面是一个简单的示例代码: ``` public class ThreadLocalExample { private static final ThreadLocal<String> THREAD_LOCAL = new ThreadLocal<>(); public static void main(String[] args) { THREAD_LOCAL.set("Hello, world!"); Thread thread1 = new Thread(() -> { THREAD_LOCAL.set("Hello from thread 1!"); System.out.println(THREAD_LOCAL.get()); }); Thread thread2 = new Thread(() -> { THREAD_LOCAL.set("Hello from thread 2!"); System.out.println(THREAD_LOCAL.get()); }); thread1.start(); thread2.start(); System.out.println(THREAD_LOCAL.get()); } } ``` 在上面的示例中,我们创建了一个ThreadLocal对象`THREAD_LOCAL`用于存储String类型的变量。首先我们通过调用`THREAD_LOCAL.set("Hello, world!")`方法在主线程中设置了变量的值。然后,我们创建了两个新的线程并分别在其中设置了不同的值,并打印出来。最后,在主线程中我们也打印了变量的值。 运行上面的代码,你会看到输出结果类似于: ``` Hello from thread 1! Hello from thread 2! Hello, world! ``` 可以看到,每个线程都可以独立地访问和修改自己的变量副本,不会对其他线程产生影响。这样就确保了在多线程环境中,每个线程都可以维护自己的变量状态。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值