并发编程-导致JVM内存泄漏的ThreadLocal

本文详细介绍了ThreadLocal的工作原理及其在并发编程中的作用,特别是其如何帮助解决数据库连接和事务管理问题。同时,文章揭示了ThreadLocal可能导致内存泄漏的场景,分析了内存泄漏的原因,强调了在不再需要ThreadLocal时调用`remove()`的重要性。通过对比不同处理哈希冲突的方法,展示了ThreadLocal高效性能的原因。最后,文章提醒读者在使用线程池和ThreadLocal时要谨慎,避免内存资源的浪费。
摘要由CSDN通过智能技术生成

为什么要有ThreadLocal

我们首先来看看一段最纯粹的原生JDBC代码

0

0

0

可以看到,在使用JDBC时,我们首先要配置后再拿到JDBC连接,然后在增删改查的业务方法中拿到这个连接,并把我们的SQL语句交给JDBC连接发送到真实的DB上执行。

在实际的工作中,我们不会每次执行SQL语句时临时去建立连接,而是会借助数据库连接池,同时因为实际业务的复杂性,为了保证数据的一致性,我们还会引入事务操作,于是上面的代码就会变成:

0

0

0

        但是上面的代码包含什么样的问题呢?分析代码我们可以发现,执行业务方法business时,为了启用事务,我们从数据库连接池中拿了一个连接,但是在具体的insert方法和getAll方法中,在执行具体的SQL语句时,我们从数据库连接池中拿一个连接,这就说执行事务和执行SQL语句完全是不同的数据库连接,这会导致什么问题?事务失效了!!数据库执行事务时,事务的开启和提交、语句的执行等都是必须在一个连接中的。实际上,上面的代码要保证数据的一致性,就必须要启用分布式事务。

        怎么解决这个问题呢?有一个解决思路是,把数据库连接作为方法的参数,在方法之间进行传递,比如下面这样:

0

0

0

        但是我们分析平时我们使用SSM的代码会发现,我们在编写数据访问相关代码的时候从来没有把数据库连接作为方法参数进行传递。这意味着,对Spring来说,在帮我们进行事务托管的时候,会遇到同样的问题,那么Spring是如何解决这个问题的?

        其实稍微分析下Spring的事务管理器的代码就能发现端倪,在org.springframework.jdbc.datasource.DataSourceTransactionManager#doBegin中,我们会看到如下代码

0

上面的注释已经很清楚了说明“绑定连接到这个线程”,如何绑定的?继续深入看看

0

0

0

看来,Spring是使用一个ThreadLocal来实现“绑定连接到线程”的。

现在我们可以对ThreadLocal下一个比较确切的定义了

This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable. ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).

        此类提供线程局部变量。这些变量与普通对应变量的不同之处在于,访问一个变量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长情知热爱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值