Java并发来一发(十四)ThreadLocal

1、ThreadLocal简介

java.lang.ThreadLocal是线程本地变量,意为每个线程私有的变量,不同线程间不共享。

它的意义在于线程间的数据隔离。

ThreadLocal有个内部类ThreadLocalMap,key就是当前线程,value就是线程正在执行的任务中的某个变量的包装类Entry。

2、ThreadLocal使用姿势

ThreadLocal变量需要定义为static,原因是非static变量的实例会有多个,也就是会有多个ThreadLocal实例,这是没必要的,只是增加了内存消耗。而static ThreadLocal 的ThreadLocalMap在每个线程都有一个副本。

3、ThreadLocal应用

常见的ThreadLocal使用场景为数据库连接、Session管理等。

数据库连接管理类,原本可以用同步或锁保证线程安全,但这会影响效率。这个场景的特点是,每个线程都有connect请求,但各自的连接之间是没有依赖的关系的,也就是每个线程各自管理好各自的小线程池就够了,那么这正好是ThreadLocal擅长做的事。代码参考如下(来自参考资料):

private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<Connection>() {
    public Connection initialValue() {
	    return DriverManager.getConnection(DB_URL);
    }
};

public static Connection getConnection() {
    return connectionHolder.get();
}

4、ThreadLocal的坑

由于ThreadLoacal是和线程绑定的,也就是说ThreadLocal变量的生命周期是和线程一样的,理论上线程结束后ThreadLocal就回收了。可是在线程池中,对线程的管理是线程会复用,线程往往不会注销,这意味着ThreadLocal的生命周期和JVM一致。这会导致什么问题呢?

假设ThreadLocal中存了一个HashMap,如果业务上HashMap的key不断变化,那么HashMap会不断变长。由于对HashMap数据的写入,一般会先校验这个HashMap是否已经存在,若不存在,则创建一个,若存在,一般为避免未知的业务异常也不会替换掉。这样的HashMap实例越来越多,会逐渐形成内存泄露而无法管理。

线程池使用ThreadLocal时,如果没有及时remove,而下一个线程没有调用set方法,那么get到的就会是错误信息。

参考资料:

https://www.iteye.com/topic/103804 这篇文章写的非常不错,推荐

http://www.cnblogs.com/yxysuanfa/p/7125761.html ThreadLocal的坑

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值