博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ThreadLocal在实际项目中的应用
阅读量:4220 次
发布时间:2019-05-26

本文共 3638 字,大约阅读时间需要 12 分钟。

首先,分析下ThreadLocal的源码:

在分析ThreadLocal的具体用法前,我们来看下ThreadLocal对外提供的三个方法(set、get、delete)的源码:
1)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);}
分析:
可以看到,当某个线程在具体调用ThreadLocal的set方法时,除了设置要保存的自身变量外,还保存了当前线程的信息(this)。
2)get方法 获取变量
public T get() {    Thread t = Thread.currentThread();    ThreadLocalMap map = getMap(t);    if (map != null) {        ThreadLocalMap.Entry e = map.getEntry(this);        if (e != null) {            @SuppressWarnings("unchecked")            T result = (T)e.value;            return result;        }    }    return setInitialValue();}
分析
map.getEntry(this)获取当前线程this的信息,并把相应的值取出来。
3)remove方法 移除变量
public void remove() {    ThreadLocalMap m = getMap(Thread.currentThread());    if (m != null)        m.remove(this);}
分析:
一般来说一次使用完之后,要把相应的值去除掉,防止内存泄漏。

其次,在实际项目中应用:比如:保存本次请求用户的信息、logId或者一些需要在一次request时需要都用的数据:
举个栗子如下:

1、
uitls包下,定义一个
ThreadLocalUtil.java类:
public class ThreadLocalUtil {    private final static ThreadLocal
threadLocal = new ThreadLocal<>(); public static void add(Long id) { threadLocal.set(id); } public static Long getId() { return threadLocal.get(); } public static void remove() { threadLocal.remove(); }}
2、在包filter下,定义一个过滤器HttpFilter.java类:
@Slf4jpublic class HttpFilter implements Filter {    @Override    public void init(FilterConfig filterConfig) throws ServletException {    }    @Override    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {        HttpServletRequest reqeust = (HttpServletRequest)servletRequest;        log.info("do filter, {}, {}", Thread.currentThread().getId(), reqeust.getServletPath());        ThreadLocalUtil.add(Thread.currentThread().getId());        filterChain.doFilter(servletRequest, servletResponse);    }    @Override    public void destroy() {    }}
3、在SpringBootDemoApplication.java中,配置过滤器:
@Beanpublic FilterRegistrationBean httpFilter() {   FilterRegistrationBean registrationBean = new FilterRegistrationBean();   registrationBean.setFilter(new HttpFilter());   registrationBean.addUrlPatterns("/*");   return registrationBean;}
4、在包interceptor下,添加拦截器HttpIntercrptor.java类:
@Slf4jpublic class HttpInterceptor extends HandlerInterceptorAdapter {    @Override    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)            throws Exception {        log.info("preHandle");        return true;    }    @Override    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,                                @Nullable Exception ex) throws Exception {        ThreadLocalUtil.remove();        log.info("afterCompletion");    }}
5、在包config下配置拦截器InterceptorConfig.java类如下:
@Configurationpublic class InterceptorConfig implements WebMvcConfigurer {    @Override    public void addInterceptors(InterceptorRegistry registry) {        registry.addInterceptor(new HttpInterceptor()).addPathPatterns("/**");    }}
6、编写测试控制层如下:
@GetMapping("/test4")public String getTest4() {    return ThreadLocalUtil.getId().toString();}
分析:
一般在Java web中使用ThreadLocal时,在过滤器filter中设置set相应的值,然后,为了防止内存泄漏,在拦截器的afterComletion中进行remove移除相应的变量值。

补充知识点:
线程封闭
什么是线程封闭:
把对象封装到一个线程中,只有这个线程能看到这个对象,那么这个对象就算不是线程安全的,也不会出现线程安全的问题。
实现线程封闭的方法:
1)Ad-hoc 线程封闭:程序控制实现,最糟糕,忽略
2)堆栈封闭:局部变量,无并发问题。(即:多个线程访问一个方法中的局部变量,都会把局部变量拷贝一份到线程的堆栈中)
3)ThreadLocal线程封闭:特别好的封闭方法 (ThreadLocal中维护了一个map,map的key是线程的名称,value是我们存储的对象)

转载地址:http://pgomi.baihongyu.com/

你可能感兴趣的文章
C语言文件操作详解
查看>>
C语言详解 FILE文件操作
查看>>
磁盘I/O那些事
查看>>
Linux下的IO监控与分析
查看>>
ZeroMQ
查看>>
ZeroMQ编译安装使用教程
查看>>
Linux配置ntp时间服务器(全)
查看>>
Linux Wireless架构总结
查看>>
带宽与延时知识整理
查看>>
无线电信号怎么传输的
查看>>
wifi提速技巧:十大方法瞬间提升wifi速度
查看>>
WIFI 的 传输信道 与标准 WIFI的频道 传输能力
查看>>
CAN网络学习总结
查看>>
Linux CAN说明文档
查看>>
freescale IMX6Q git 获取源码
查看>>
Freesclae i.MX6 Linux PCIE驱动源码分析
查看>>
(一)Yocto的介绍
查看>>
卡尔曼滤波,最最容易理解的讲解.找遍网上就这篇看懂了
查看>>
SLAM的前世今生 终于有人说清楚了
查看>>
激光定位原理的理解
查看>>