ThreadLocal详解

ThreadLocal概要

我们可以使用synchorinized 关键字来为变量加锁以解决线程安全问题,从而限制只能有一个线程来使用此变量,但是加锁会大大影响程序执行效率

ThreadLocal是线程局部变量(从线程的角度看,目标变量就像是线程的本地变量), 通常是类中的 private static 字段. 当ThreadLocal维护变量的时候,为每一个使用该变量的线程都提供一个独立的变量副本.即每个线程内部都会有一个该变量,这样同时多个线程访问该变量并不会彼此相互影响.这样就不存在线程安全问题。但是由于在每个线程中都创建了副本,所以它对内存资源的消耗要大一些,其实它采用了空间换时间的思想

Thread 在内部是通过ThreadLocalMap来维护ThreadLocal变量表, 在Thread类中有一个threadLocals 变量,是ThreadLocalMap类型的,它就是为每一个线程来存储自身的ThreadLocal变量的, ThreadLocalMap是ThreadLocal类的一个内部类,这个Map里面可以有多个Entry, 每一个Entry使用ThreadLocal作为key, 变量作为 value

(1)ThreadLocal模式至少从两个方面完成了数据访问隔离,即纵向隔离(线程与线程之间的ThreadLocalMap不同)和横向隔离(不同的ThreadLocal实例之间的互相隔离)

(2)ThreadLocalMap变量属于线程的内部属性,不同的线程拥有完全不同的ThreadLocalMap变量;

(3)线程中的ThreadLocalMap变量的值是在ThreadLocal对象进行set或者get操作时创建的;

在上图中的一个Thread的这个ThreadLocalMap中分别存放了3个Entry。每一个Entry对象存放的是一个ThreadLocal变量对象。

ThreadLocal方法

public T get() { } // 用来获取该ThreadLocal在当前线程中保存的变量副本

public void set(T value) { } //用来设置当前线程中变量的副本

public void remove() { } //remove()用来移除当前线程中变量的副本

protected T initialValue() { } //initialValue()是一个protected方法,一般是用来在使用时进行重写的

ThreadLocal的使用场景

​​​​​​​ThreadLocal可能引起的OOM内存溢出问题

我们知道ThreadLocal变量是维护在Thread内部的,这样的话只要我们的线程不退出,对象的引用就会一直存在。当线程退出时,Thread类会进行一些清理工作,其中就包含ThreadLocalMap,Thread在源码中是调用exit方法进行清理的。但是当我们使用线程池的时候,就意味着当前线程未必会退出(比如固定大小的线程池,线程总是存在的)。如果这样的话,将一些很大的对象设置到ThreadLocal中(这个很大的对象实际保存在Thread的threadLocals属性中),这样的话就可能会出现内存溢出的情况。ThreadLocal在没有线程池使用的情况下,正常情况下不会存在内存泄露,但是如果使用了线程池的话,就依赖于线程池的实现,如果线程池不销毁线程的话,那么就会存在内存泄露。所以我们在使用线程池的时候,使用ThreadLocal要格外小心!​​​​​​​

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值