【学习笔记】深入理解ThreadLocal(2)

简介: 【学习笔记】深入理解ThreadLocal

三 案例

目录结构:

屏幕快照 2022-05-10 下午12.58.46.png

HttpFilter.java

package com.lyy.threadlocal.config;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@Slf4j
public 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 request = (HttpServletRequest)servletRequest;
//        request.getSession().getAttribute("user");
        System.out.println("do filter:"+Thread.currentThread().getId()+":"+request.getServletPath());
        RequestHolder.add(Thread.currentThread().getId());
        //让这个请求完,,同时做下一步处理
        filterChain.doFilter(servletRequest,servletResponse);
    }
    //不再使用的时候做的事情
    @Override
    public void destroy() {
    }
}

HttpInterceptor.java

package com.lyy.threadlocal.config;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HttpInterceptor extends HandlerInterceptorAdapter {
    //接口处理之前
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle:");
        return true;
    }
    //接口处理之后
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        RequestHolder.remove();
       System.out.println("afterCompletion");
        return;
    }
}

RequestHolder.java

package com.lyy.threadlocal.config;
public class RequestHolder {
    private final static ThreadLocal<Long> requestHolder = new ThreadLocal<>();//
    //提供方法传递数据
    public static void add(Long id){
        requestHolder.set(id);
    }
    public static Long getId(){
        //传入了当前线程的ID,到底层Map里面去取
        return requestHolder.get();
    }
    //移除变量信息,否则会造成逸出,导致内容永远不会释放掉
    public static void remove(){
        requestHolder.remove();
    }
}

ThreadLocalController.java

package com.lyy.threadlocal.controller;
import com.lyy.threadlocal.config.RequestHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/thredLocal")
public class ThreadLocalController {
    @RequestMapping("test")
    @ResponseBody
    public Long test(){
        return RequestHolder.getId();
    }
}

ThreadlocalDemoApplication.java

package com.lyy.threadlocal;
import com.lyy.threadlocal.config.HttpFilter;
import com.lyy.threadlocal.config.HttpInterceptor;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@SpringBootApplication
public class ThreadlocalDemoApplication extends WebMvcConfigurerAdapter {
    public static void main(String[] args) {
        SpringApplication.run(ThreadlocalDemoApplication.class, args);
    }
    @Bean
    public FilterRegistrationBean httpFilter(){
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        registrationBean.setFilter(new HttpFilter());
        registrationBean.addUrlPatterns("/thredLocal/*");
        return registrationBean;
    }
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new HttpInterceptor()).addPathPatterns("/**");
    }
}

屏幕快照 2022-05-10 下午1.00.00.png

四 总结


1、ThreadLocal是通过每个线程单独一份存储空间,每个ThreadLocal只能保存一个变量副本。

2、相比于Synchronized,ThreadLocal具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问到想要的值,很好的实现了线程封闭。

3、每次使用完ThreadLocal,都调用它的remove()方法,清除数据,避免内存泄漏的风险

4、通过上面的源码分析,我们也可以看到大神在写代码的时候会考虑到整体实现的方方面面,一些逻辑上的处理是真严谨的,我们在看源代码的时候不能只是做了解,也要看到别人实现功能后面的目的。


源码地址:https://github.com/839022478/other/tree/master/threadlocal_demo


目录
相关文章
|
存储 安全 Java
【ThreadLocal】
【ThreadLocal】
|
6月前
|
存储 安全 Java
面试题:用过ThreadLocal吗?ThreadLocal是在哪个包下的?看过ThreadLocal源码吗?讲一下ThreadLocal的get和put是怎么实现的?
字节面试题:用过ThreadLocal吗?ThreadLocal是在哪个包下的?看过ThreadLocal源码吗?讲一下ThreadLocal的get和put是怎么实现的?
78 0
|
4月前
|
存储 Java
ThreadLocal应用及理解
ThreadLocal应用及理解
45 10
|
5月前
|
Java
ThreadLocal 场景题
ThreadLocal 场景题
35 1
|
11月前
|
存储
ThreadLocal
ThreadLocal
52 0
|
存储 Java
|
Java
ThreadLocal笔记
ThreadLocal笔记
202 0
ThreadLocal笔记
|
存储 前端开发 Java
ThreadLocal学习笔记(一)
ThreadLocal学习笔记(一)
ThreadLocal学习笔记(一)
|
存储 分布式计算 安全
什么是ThreadLocal?
这篇文章是慕课网上一门免费课程《ThreadLocal》的观后总结。这门课将ThreadLocal讲得非常清晰易懂,又深入底层原理和设计思想,是我看过的最好的ThreadLocal的资料,现在把用自己的话,把它整理成文字版本。 总共预计产出四篇文章,这是第一篇。
266 3
|
存储 安全 Java
ThreadLocal 使用详解
ThreadLocal 是线程本地变量。当使用 ThreadLocal 维护变量时,ThreadLocal 为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程
543 0