【学习笔记】深入理解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


目录
相关文章
|
11月前
|
存储 安全 Java
【ThreadLocal】
【ThreadLocal】
|
2月前
|
存储 算法 Java
ThreadLocal 源码浅析
【7月更文挑战第5天】`ThreadLocal` 是Java中用于创建线程局部变量的工具类,确保每个线程拥有独立的变量副本。源码中,每个`ThreadLocal`实例都有一个唯一的哈希码用于映射到`ThreadLocalMap`,这个内部静态类使用弱引用存储键(`ThreadLocal`实例)以防止内存泄漏。`ThreadLocalMap`使用 Entry 数组,Entry 是一个扩展了 WeakReference 的类,持有线程变量值。`ThreadLocal`的`get()`和`set()`方法通过哈希计算定位并访问或设置线程局部变量。
|
3月前
|
Java
ThreadLocal 场景题
ThreadLocal 场景题
23 1
|
4月前
|
存储 Java 数据管理
ThreadLocal的使用
`ThreadLocal`是Java中的线程局部变量工具,确保每个线程都有自己的变量副本,互不干扰。适用于保持线程安全性数据和跨方法共享数据。基本用法包括创建实例、设置和获取值以及清除值。例如,创建ThreadLocal对象后,使用`.set()`设置值,`.get()`获取值,`.remove()`清除值。注意ThreadLocal可能引起内存泄漏,应适时清理,并谨慎使用以避免影响代码可读性和线程安全性。它是多线程编程中实现线程局部数据管理的有效手段。
77 10
|
存储 算法 安全
深入详解ThreadLocal
在我们日常的并发编程中,有一种神奇的机制在静悄悄地为我们解决着各种看似棘手的问题,它就是 ThreadLocal 。
21479 9
深入详解ThreadLocal
|
12月前
|
存储 Java
ThreadLocal
ThreadLocal字面意思本地线程,ThreadLocal使每个线程之间是隔离的,数据是独立的,我们使用过session都知道 session是一个会话,我们可以用它来存储一些用户的基本信息,这样每个用户在服务端都能取到,ThreadLocal也可以做到, ThreadLocal将相应的信息存储在当前的线程中,只有当前线程能够访问,其他线程不能访问,其实ThreadLocal 可以说是一个定制化的Map。
48 0
|
Java
ThreadLocal笔记
ThreadLocal笔记
187 0
ThreadLocal笔记
|
存储 前端开发 Java
ThreadLocal学习笔记(一)
ThreadLocal学习笔记(一)
ThreadLocal学习笔记(一)
|
存储 Java
ThreadLocal相关使用
ThreadLocal相关使用
183 0
ThreadLocal相关使用
|
存储 Java
对threadlocal了解多少?
通常情况下,我们创建的变量是可以被任何一个线程访问并修改的。如果想实现每一个线程都有自己的专属本地变量该如何解决呢? JDK 中提供的 ThreadLocal 类正是为了解决这样的问题。 ThreadLocal 类主要解决的就是让每个线程绑定自己的值,可以将 ThreadLocal 类形象的比喻成存放数据的盒子,盒子中可以存储每个线程的私有数据。