关于ThreadLocal的使用场景

直接上代码:

 

package com.weigu.zjp.ThreadLocal;

public class BaseSignatureRequest {
    private String device;

    public String getDevice() {
        return device;
    }

    public void setDevice(String device) {
        this.device = device;
    }
}

 

package com.weigu.zjp.ThreadLocal;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ParameterInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String device = request.getParameter("device");
        BaseSignatureRequest baseSignatureRequest = new BaseSignatureRequest();
        baseSignatureRequest.setDevice(device);
        ThreadLocalCache.baseSignatureRequestThreadLocal.set(baseSignatureRequest);
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        ThreadLocalCache.baseSignatureRequestThreadLocal.remove();
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest,
                           HttpServletResponse httpServletResponse,
                           Object o, ModelAndView modelAndView) throws Exception {

    }
}

 

package com.weigu.zjp.ThreadLocal;

public class ThreadLocalCache {
    public static ThreadLocal<BaseSignatureRequest>
            baseSignatureRequestThreadLocal = new ThreadLocal<>();
}

 

当然需要在 spring里面配置 interceptor

 <mvc:interceptors>
 <mvc:interceptor>
 <mvc:mapping path="/api/**"/>
 <bean class="life.majiang.ParameterInterceptor"></bean>
 </mvc:interceptor>
 </mvc:interceptors>

 

:在调用API接口的时候传递了一些公共参数,这些公共参数携带了一些设备信息,服务端接口根据不同的信息组装不同的格式数据返回给客户端。假定服务器端需要通过设备类型(device)来下发下载地址,当然接口也有同样的其他逻辑,我们只要在返回数据的时候判断好是什么类型的客户端就好了

关于他的源码:

 

get方法

 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();
 }
public T get() { }
public void set(T value) { }
public void remove() { }
protected T initialValue() { }

get()方法是用来获取 ThreadLocal在当前线程中保存的变量副本

set()用来设置当前线程中变量的副本

remove()用来移除当前线程中变量的副本

initialValue()是一个 protected方法,一般是用来在使用时进行重写的,如果在没有set的时候就调用 get,会调用 initialValue方法初始化内容。

为了使用的更放心,我们简单的看一下具体的实现:

set方法

 public void set(T value) {
 Thread t = Thread.currentThread();
 ThreadLocalMap map = getMap(t);
 if (map != null)
 map.set(this, value);
 else
 createMap(t, value);
 }

set方法会获取当前的线程,通过当前线程获取 ThreadLocalMap对象。然后把需要存储的值放到这个 map里面。如果没有就调用 createMap创建对象。

getMap方法

 ThreadLocalMap getMap(Thread t) {
 return t.threadLocals;
 }

getMap方法直接返回当前 Thread的 threadLocals变量,这样说明了之所以说 ThreadLocal是 线程局部变量就是因为它只是通过 ThreadLocal把 变量存在了 Thread本身而已。

createMap方法

 void createMap(Thread t, T firstValue) {
 t.threadLocals = new ThreadLocalMap(this, firstValue);
 }

在 set的时候如果不存在 threadLocals,直接创建对象。由上看出,放入 map的 key是当前的 ThreadLocal, value是需要存放的内容,所以我们设置属性的时候需要注意存放和获取的是一个 ThreadLocal。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值