ThreadLocal 详解(一)

一、ThreadLocal简介

        Threadlocal叫做线程变量,意思是Treadlocal中填充的变量数据当前线程,该变量对其他线程而言是隔离的,并且变量在整个的生命周期有效。Threadlocal会为每个线程中都创建一个副本,那么每个线程可以访问自己内部的副本变量。

        Threadlocal内部通过Ma来存储每一个线程的变量副本,Map的Key就是当前的Threadlocal,Value值就是我们set的那个值,每次线程在get时候,都从自己的变量中取值,所以不会存在线程安全问题;注意:使用Thradlocal后,一直要手动remove(),否则会造成OOM异常;Threadlocal提供了线程本地实例,它与普通变量的却别在于每个使用该变量的线程都会初始化一个完全独立的实例副本。Threadlocal变量通常被private static修饰。当一个线程结束时,他所使用的Threadlocal相对的实例副本都可被回收。

二、ThreadLocal可以解决多线程环境下的上下文传递问题,它提供了以下主要功能

  •  上下文隔离:每个线程可以通过Threadlocal独立存储和访问自己的数据,不同的线程之间数据相互隔离,避免了线程间数据的冲突和竞争条件;
  •  线程安全:Threadlocal提供了线程级别的数据副本,每个线程都可以独立的操作自己的数据,无需考虑并发访问的同步问题。这样可以简化编发编程的复杂性,并提高程序的性能。
  •  线程上下文传递:在多线程的环境中,可能需要在不同的方法或组件中传递上下文信息,例如用户信息、请求跟踪ID等。Threadlocal可以同一线程内共享上下文信息,,而无需显示传递参数。        

三、ThreadLocal与Synchronized的区别

        Threadlocal<T>其实是与线程绑定的一个变量。Threadlocal和synchonzied都用于结局并发问题,但是Threadlocal与synchronized有本质区别。

  1. Synchroized用于线程间的数据共享,而Thradlocal则用于线程间的数据隔离。
  2. Synchroized是利用锁的机制,使变量或代码块在某一时刻只能被一个线程访问。而Threadlocal每一个线程都提供了变脸的副本,使得每个线程在某一时间访问到的并不是同一对象,这样就隔离了多个线程对数据的数据共享。而Synchroized却正好相反,它用于在多个线程间通信时能够获得数据共享;

四、ThreadLocal使用场景

  • 记录每次请求用户信息

ThreadLocal代码:

public class RequestHolder {

    private static final ThreadLocal<SysUser> userHolder = new ThreadLocal<SysUser>();


    public static void setUser(SysUser sysUser) {
        userHolder.set(sysUser);
    }

    public static SysUser getUser() {
        return userHolder.get();
    }

    public static void remove() {
        userHolder.remove();
    }
}

获取用户值

// 1、拦截器获取用户信息
// 2、记录到ThreadLocal中
@Component
public class AuthenticationHandlerInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.debug("进入拦截器,URL:{}", request.getServletPath());

        // 加入用户全局信息
        RequestHolder.setUser(userInfo);
        return true;
    }
    ....
    ....
}

// 3、使用时通过get()方法获取值
@RestController
@RequestMapping
public class Controller {
   .....
    @GetMapping("/test")
    public String test() {
    	// 从ThreadLocal获取数据
    	RequestHolder.getUserId();
        return "访问成功";
    }
   .....
}

结尾:喜欢的朋友点个赞吧!

  • 20
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值