【数据库连接,线程,ThreadLocal三者之间的关系】

一、数据库连接与线程的关系

在实际项目中,数据库连接是很宝贵的资源,以MySQL为例,一台MySQL服务器最大连接数默认是100, 最大可以达到16384。但现实中最多是到200,再多MySQL服务器就承受不住了。因为mysql连接用的是tcp协议,稳定的同时意味着需要消耗更多时间和性能去建立维持连接。为了能最大利用如此宝贵的数据库连接,我们希望数据库连接能被复用而不需要频繁创建,所以利用池化技术建立数据库连接池。

了解连接池在多线程场景中是如何工作的。 一个连接池包含多个连接对象。我们可以配置池的大小。 当多个线程需要并发访问一个数据库时,它们会从连接池中请求连接对象。 如果池中仍有空闲连接,线程将获取连接对象并开始其数据库操作。线程完成工作后,会将连接返回到池中。 如果池中没有空闲连接,线程将等待另一个线程将连接对象返回到池中。 所以,一个连接在同一时间只能被一个线程所持有,一个线程在同一时间也只能申请到一个连接,官方也不鼓励在多个线程之间共享连接对象

明白了这点之后再看下线程,我们知道一个线程在生命周期内会做很多事情,比如参数校验,权限验证,数值计算,然后持久化结果。其中可能只有持久化结果环节需要访问JDBC数据库连接,其余的时间范围内,JDBC数据库连接 都是空闲状态。所以如果线程整个生命周期中独占JDBC数据库连接的话,那么这个连接空闲率就很高也就变得很浪费,因为一旦占用了数据库连接可以不限次数执行事务SQL请求,增删查改各种sql操作请求都可以执行。为了提高数据库连接的使用率,目前普遍的解决方案是:当线程需要做数据库操作时,才会真正请求获取JDBC数据库连接,线程使用完了之后,立即释放,被释放的JDBC数据库连接等待下次分配使用。

二、多线程访问同一个数据库连接

前面已经说了,数据库连接在同一时间只能被一个线程所持有,线程在申请数据库连接时也是线程安全的。
Java多线程访问同一个java.sql.Connection会导致事务错乱。解决多个线程访问同一个Connection对象时,必须遵循两个基本原则:

  • 以资源互斥的方式访问Connection对象;
  • 在线程执行结束时,应当最终及时提交(commit)或回滚(rollback)对Connection的影响;不允许存在尚未被提交或者回滚的语句。

ThreadLocal的原理
想了解下ThreadLocal的原理可以看下这篇文章:ThreadLocal就是这么简单
ThreadLocal和Thread的关系如下图:
在这里插入图片描述

ThreadLocal里面定义了ThreadLocalMap这个静态内部类。而Thread类里持有了ThreadLocalMap的引用。


    /**
     * Variant of set() to establish initialValue. Used instead
     * of set() in case user has overridden the set() method.
     *
     * @return the initial value
     */
    private T setInitialValue() {
        T value = initialValue();
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
        return value;
    }

    /**
     * Create the map associated with a ThreadLocal. Overridden in
     * InheritableThreadLocal.
     *
     * @param t the current thread
     * @param firstValue value for the initial entry of the map
     */
    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }
  • ThreadLocal在初始化时会对当前线程所持有的ThreadLocalMap引用进行实例化。
  • ThreadLocal的set方法即是拿出当前线程所持有的ThreadLocalMap引用,然后将所要保存的值塞进这个map里,key是ThreadLocal
  • ThreadLocal的get方法是根据当前线程所持有的ThreadLocalMap引用,用ThreadLocal 这个key拿出value。

三、ThreadLocal 与多线程还有数据库连接的关系

我们经常听说ThreadLocal的目的是为了解决多线程访问资源时的共享问题。这种说法是完全错误的。
ThreadLocal的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度。

举个例子,一个线程的生命周期要做这么几件事情:参数校验,业务逻辑1,数据持久化,业务逻辑2,数据库切换,业务逻辑3。

==该线程在进行数据持久化时需要申请数据库连接,当做完之后就将连接释放回线程池,但之后进行数据库切换时也需要数据库连接,这时候继续申请吗?不是的,==这时ThreadLocal就派上用场了,在第一次数据持久化操作做完之后,将这个数据库连接暂存在ThreadLocal中,在之后的数据库切换中需要用到时再拿出来用。由此可见,ThreadLocal对线程来说相当于提供一个局部变量,线程把资源用完之后先放到ThreadLocal里,之后需要用到时再拿出来。在多租户场景下,因为经常需要切换数据库,所以ThreadLocal很常用。 那么在多线程场景下ThreadLocal的表现是咋样呢?
在这里插入图片描述

如图所示,多线程下,不同线程会持有不同的ThreadLocalMap引用,但这些ThreadLocalMap的key都是指向同个ThreadLocal对象,所以可以理解为什么代码中在用到ThreadLocal时都会设为static了吧,就是为了让多线程下ThreadLocalMap的key都使用的是同一个ThreadLocal,这是JDK1.3之后的改进,这样设计之后每个Map的Entry数量变小了:之前key是Thread,Thread有多少个就会导致key有多少个,现在是ThreadLocal的数量,能提高性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/6472.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JAVA:常用API

一.什么是API? API(Application Programming Interface):应用程序编程接口。 简单的来说:就是Java帮我们已经写好的方法,我们可以直接使用。 二.有哪些常用的API? Object、Objects、StringB…

二战华为成功上岸,准备了小半年,要个27k应该也算不上很高吧~

先说下我基本情况,本科不是计算机专业,现在是学通信,然后做图像处理,可能面试官看我不是科班出身没有问太多计算机相关的问题,因为第一次找工作,华为的游戏专场又是最早开始的,就投递了&#xf…

二,八,十,十六进制等常用进制详解

总目录 文章目录总目录一、常用进制1、进制基本信息2、各进制的表示形式二、进制转换原理1、其他进制转为十进制计算原理2、十进制转为其他进制计算原理3、二进制,八进制,十六进制之间的转换结语一、常用进制 1、进制基本信息 基数数码名称描述20 和 1…

【C++】| C/C++内存管理

前言: 在上期,我们已经对类和对象的全部知识进行了总结和梳理。在类和对象学习完之后,今天我将给大家呈现的是关于——C/C内存管理的基本知识。 本文目录 1. C/C内存分布 2. C语言中动态内存管理方式 (1)C语言跟内…

php科研项目申报审批系统

目 录 1 绪论 4 1.1 开发背景 4 1.2 开发意义 4 1.3 相关知识介绍 4 1.3.1 Apache 4 1.3.2 MySQL 5 1.3.3 PHP 6 1.3.4 Dreamweaver CS3 7 1.4 本文所做的工作及组织结构 7 2 系统分析 7 2.1 需求分析 7 2.2 可行性分析 7 2.3 系统界面…

CSDN博客专家证书发放名单(2023年3月已更新)

目录 证书发放频次 6月(第一批)证书发放名单(80位) 7月(第二批)证书发放名单(50位) 8月(第三批)证书发放名单(54位) 9月&#xf…

2个月月活突破1亿,增速碾压抖音,出道即封神的ChatGPT,现在怎么样了?ChatGPT它会干掉测试?

从互联网的普及到智能手机,都让广袤的世界触手而及,如今身在浪潮中的我们,已深知其力。 前阵子爆火的ChatGPT,不少人保持观望态度。现如今,国内关于ChatGPT的各大社群讨论,似乎沉寂了不少,现在…

Prometheus监控实战之Exporter详解

1 exporter是什么? 广义上向prometheus提供监控数据的程序都可以成为一个exporter的,一个exporter的实例称为target, exporter来源主要2个方面,一个是社区提供的,一种是用户自定义的。 2 常用exporter 官方和一些社区提供好多ex…

彻底关闭Windows自动更新

彻底关闭Windows自动更新 目录 彻底关闭Windows自动更新 前言 Windows10彻底关闭自动更新方法步骤: 一、禁用Windows Update服务 二、在组策略里关闭Win10自动更新相关服务 三、禁用任务计划里边的Win10自动更新 四、在注册表中关闭Win10自动更新 前言 我们用…

易语言支持库配置闪退丨支持库配置崩溃_易语言打开支持库配置就闪退怎么办?

易语言支持库配置闪退打不开怎么办? 易语言支持库配置闪退解决方法丨支持库配置崩溃_易语言打开支持易语言支持库配置闪退丨支持库配置崩溃_易语言打开支持库配置就闪退怎么办? 很多人都遇到过 打开易语言支持库安装菜单报错退出的问题 今天教大家解决方法 我们…

4.2--Redis总结之高可用篇(关于哨兵机制)---(温故而知新篇)--加油呀

1.为什么要有哨兵机制? 在 Redis 的主从架构中,由于主从模式是读写分离的,如果主节点挂了,那么将没有主节点来服务客户端的写操作请求,也没有主节点给从节点进行数据同步了 哨兵机制,它的作用是实现主从节…

spring集成mybaits以注解方式完成连表查询练习

题目: 以注解的方式完成连表查询 1、查询全部员工信息,要求显示部门名称 2、根据姓名模糊查询员工信息 自己看完,建一个简单的员工表和部门表。 1、先创建一个maven模块,这里直接建的普通…

SpringMVC --- 获取请求参数、域对象共享数据、视图

一、SpringMVC获取请求参数 1.1、通过ServletAPI获取 将 HttpServletRequest 作为控制器方法的形参,此时 HttpServletRequest 类型的参数表示封装了当前请求的请求报文的对象 RequestMapping("/param/servletAPI")public String getParamByServletAPI(H…

从零开始实现一个C++高性能服务器框架----配置模块

此项目是根据sylar框架实现,是从零开始重写sylar,也是对sylar丰富与完善 项目地址:https://gitee.com/lzhiqiang1999/server-framework 简介 项目介绍:实现了一个基于协程的服务器框架,支持多线程、多协程协同调度&am…

【C++】多态(下)

文章目录1.单继承中的虚函数表整体代码用程序打印虚表如何寻找到虚表地址虚表存在哪里?2.多继承中的虚函数表整体代码寻找虚表地址注意事项多继承重写后的func1的地为什么地址不同?ptr1调用函数——一次jmpptr2 调用函数——多次jmp1.单继承中的虚函数表…

window环境 python ide 安装教程分享

一、 右键-以管理员身份运行 python.exe(以安装 3.8 的为例,安 装方法是一样的哈) 二、选择你的安装方式。 特别注意:需要把 Add Python ** to PATH 勾选上 ②Customize installation 是自定义安装,安装位置你可以自己…

链表【左程云:Java】

一、单链表 1.单链表的节点结构 2.反转单向和双向链表 2.1 反转单向 package leetcode.链表;/*** author lin* creat 2022--12--12:50** https://leetcode.cn/problems/reverse-linked-list/*/ public class $_206反转链表 {public class ListNode {int val;ListNode next;L…

基于VHDL语言的汽车测速系统设计_kaic

摘 要 汽车是现代交通工具。车速是一项至关重要的指标。既影响着汽车运输的生产率,又关乎着汽车行驶有没有超速违章,还影响着汽车行驶时人们的人身安全。而伴随着我国国民的安全防范意识的逐步增强,人们也开始越来越关心因为汽车的超速而带来的极其严重…

一份sql笔试

1、 select substr(time,1,10),count(order_id),count(distinct passenger_id) from order where substr(time,1,7)2023-08 group by substr(time,1,10) order by substr(time,1,10);2、 select city_id from (select * from order where substr(time,1,7) 2022-08) t1 left j…

【新2023Q2押题JAVA】华为OD机试 - 打折买水果

最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为od机试,独家整理 已参加机试人员的实战技巧本篇题解:打折买水果 题目 有 m m m…