ThreadLocal的使用与原理解析

目录

基本介绍

使用方法

实际案例

ThreadLocal的实现原理

结构介绍

ThreadLocal的核心方法源码

set方法

get方法

remove方法

ThreadLocal的内存泄露问题

ThreadLocalMap扩容问题


基本介绍

从Java官方文档中的描述:ThreadLocal类用来提供线程内部的局部变量。这种变量在多线程环境下访问(通过get和set方法访问)时能保证各个线程的变量相对独立于其他线程内的变量。ThreadLocal实例通常来说都是private static类型的,用于关联线程和线程上下文。

我们可以得知 ThreadLocal 的作用是:提供线程内的局部变量,不同的线程之间不会相互干扰,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或组件之间一些公共变量传递的复杂度。
 

使用方法

public class ThreadLocalTest {
    private static ThreadLocal<String> t1 = new ThreadLocal<>();
    private String content;
    private String getContent(){
        return t1.get();
    }
    private void setContent(String content){
        t1.set(content);
    }
    public static void main(String[] args) {
        ThreadLocalTest threadLocalTest = new ThreadLocalTest();
        for (int i = 0;i<5;i++ ) {
                new Thread(()->{
                    threadLocalTest.setContent(Thread.currentThread().getName()+"的数据");
                    System.out.println("----------------------");
                    System.out.println(Thread.currentThread().getName()+"--->"+threadLocalTest.getContent());
                },"t"+i).start();
        }
    }
}

输出:

----------------------
----------------------
t2--->t2的数据
----------------------
t1--->t1的数据
----------------------
t4--->t4的数据
t0--->t0的数据
----------------------
t3--->t3的数据

        使用ThreadLocal解决了多线程之间数据隔离的问题,类似于JavaWeb中的Seesion,Session作用域是一个会话,二ThreadLocal的作用域是单个线程。

实际案例

        比如在JavaWeb的三层架构中,业务层需要处理把两个操作变成一个事务,例如转账,实际上是从账户A上减少一定数目的钱,然后再将对应数目的钱加到账户B上,为了避免这两个操作中途发生故障,导致账户A减少了钱但是账户B没有加上去,那么需要将这两操作合并成一个事务。合并成一个事务,这时就需要在业务层,数据库层调用同一个数据库connect连接对象,那么这个时候就需要将业务层的connect对象传给数据库层,那么就会增加代码的耦合度,为了减轻耦合度,我们把Connect对象放入到ThreadLocal对象里面进行储存。这样dao层直接使用线程中的Connect对象就可以了,减少了代码耦合度。

        具体实现如下:

public class JdbcUtils {
    //ThreadLocal对象 : 将connection绑定在当前线程中
    private static final ThreadLocal<Connection> tl = new ThreadLocal();

    // c3p0 数据库连接池对象属性
    private static final ComboPooledDataSource ds = new ComboPooledDataSource();

    // 获取连接
    public static Connection getConnection() throws SQLException {
        //取出当前线程绑定的connection对象
        Connection conn = tl.get();
        if (conn == null) {
            //如果没有,则从连接池中取出
            conn = ds.getConnection();
            //再将connection对象绑定到当前线程中
            tl.set(conn);
        }
        return conn;
    }

    //释放资源
    public static void release(AutoCloseable... ios) {
        for (AutoCloseable io : ios) {
            if (io != null) {
                tr
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值