数据库连接池为什么要用threadlocal?

数据库连接池引入threadlocal,是为了解决数据库事务,而事务是连接有关的,每个连接对应一个事务,多个连接的事务是不一样的!

ThreadLocal和连接池的关系:

1、连接池是缓存并托管数据库连接,主要是为了提高性能;
2、ThreadLocal缓存连接,是为了把同一个数据库连接“分享”给同一个线程的不同调用方法。不管是哪个方法都是使用同一个连接,方便进行“跨方法”的事务控制。

例:
如果一个请求中涉及多个DAO操作,而如果这些DAO的Connection都是独立的,就没有办法完成一个事务。但是如果DAO的Connection是从ThreadLocal中获得的(意味着都是同一个对象),那么这些DAO就会被纳入到同一个Connection之下。

理解连接池:

连接池里面有一定数量的连接资源,比如最大20个连接。
Java原生API 获取“直连” :

java.sql.DriverManager.getConnection(url, props);
java.sql.Driver.connect(url, props);
特点是:要传入url、用户名和密码等信息
这种方式,肯定就没有使用数据库连接池。

使用数据库连接池,通常都是得到一个所谓的javax.sql.DataSource[接口]的实例对象,它里面包含了Connection,并且数据库连接池工具类(比如C3P0、JNDI、DBCP等),肯定是重新定义了getConnection、closeConnection等方法,所以你每次得到的Connection,几乎都不是新建立的连接(而是已经建立好并放到缓存里面的连接),你调用closeConnection方法,也不是真正的关闭连接(一般都是起到一个标识作用,标识当前连接已经使用完毕,归还给连接池,让这个连接处于待分配状态)所以说:使用数据库连接池时,还是要显式的调用数据库连接池API提供的关闭连接的方法。

注意:
不同的线程在同一个时间( 或者 同一个线程在多个地方)从连接池中拿到的Connection,肯定不是同一个连接。(反之:不同时间的两个线程,一前一后,则有可能拿到同一个连接)

在公众号里面看到这样一段关于ThreadLocal和连接池的总结(链接:https://mp.weixin.qq.com/s/sJpaxoh87PHv4DZ_DQKHdw):

首先,我们为了避免单一数据库连接的创建和关闭耗费时间和性能,引入了数据库连接池,提前创建好了n条连接放入池中,如果是单线程情况下,那这样挺好的
那如果是多线程情况下呢?还是上面那段话,假设同一时间多个线程从数据库连接池获取连接,那肯定拿的是不同的连接,我当前线程和别的线程拿的连接不一样,那我当前在crud的时候,不在一个事务之内。
假设不同时间的多个线程要从数据库连接池拿连接,那这个时候就可能拿到的是同一个连接了,那我多个线程线程拿到的是同一个连接,也就是说在多个线程在同一个事务之内,线程a执行了插入还没来得及提交,线程b此时来了个更新,在线程a还未操作完之前,线程b更新完了后,直接把连接给close了,线程a插了一半发现插不了了。。。此时肯定在想,这™是谁在搞我。
为了确保不同时间多个线程可能拿到的是同一个连接,那么此时threadlocal闪亮登场,就算我拿的是“同一个连接”,在引入了threadlocal后,每个线程之间都会创建独立的连接副本,将collection各自copy一份,这样就互相不干扰了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值