当前位置: 首页 > news >正文

ThreadLocal功能实现

模拟ThreadLocal功能实现

当前线程任意方法内操作连接对象

一个栈对应一个线程 , 一个方法调用另一个方法都是在一个线程内 , 只有执行了线程的start方法才会创建一个线程

定义一个Map集合 , key是当前线程(Thread.currentThread) , value是要绑定的数据(Connection对象)

  • 以后获取,绑定,移除数据操作的key就是当前线程 , 当前线程是动态的 , 张三发起请求当前线程是t1线程 , 李四发送请求,当前线程是t2线程

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

ThreadLocal本质

自定义ThreadLocal类 , 将所有需要和当前线程绑定的数据要放到这个容器当中

public class MyThreadLocal<T> {private Map<Thread, T> map = new HashMap<>();//向ThreadLocal中当前线程绑定数据public void set(T obj){map.put(Thread.currentThread(), obj);}//从ThreadLocal中获取当前线程对应的数据public T get(){return map.get(Thread.currentThread());}//移除ThreadLocal当中当前线程对应的数据public void remove(){map.remove(Thread.currentThread());}
}

DBUtil 工具类获取当前线程绑定的Connection对象

public class DBUtil {// 静态变量特点:类加载时执行,并且只执行一次// 全局的大Map集合private static MyThreadLocal<Connection> local = new MyThreadLocal<>();//每一次都调用这个方法来获取Connection对象public static Connection getConnection(){//获取当前线程对应的Connection对象Connection connection = local.get();if (connection == null) {// 第一次调用:getConnection()方法的时候,connection一定是空的。空的就new一次。connection = new Connection();// 将new的Connection对象绑定到大Map集合中。local.set(connection);}return connection;}
}
//自定义Connection对象
public class Connection {   
}

测试从Map集合中获取当前线程绑定的Connection对象

public class Test {public static void main(String[] args) {// 调用serviceUserService userService = new UserService();userService.save();}
}
//UserService
public class UserService {private UserDao userDao = new UserDao();public void save(){//这里获取的就是当前线程绑定的Connection对象Connection connection = DBUtil.getConnection();System.out.println(connection);userDao.insert();}
}
//UserDao
public class UserDao {public void insert(){//这里获取的就是当前线程绑定的Connection对象Connection connection = DBUtil.getConnection();System.out.println(connection);System.out.println("User DAO insert");}
}

使用java.lang.ThreadLocal类优化事务

java.lang.ThreadLocal类中里面有个Map集合 , 这个集合中的key是当前线程 , value是我们想要存储的对象(如存储Connection对象)

  • 这个Map集合中的每个线程都有自己的Connection对象 , 需要的时候根据当前正在执行的线程获取对应的Connection对象
  • 每次获取的Connection对象是从ThreadLocal中的Map集合中拿的 , 第一次获取的时候需要我们手动创建并添加到Map集合中

Connection对象关闭之后,要从大Map集合中移除

  • Tomcat服务器是支持线程池的 , 线程池中有很多提前创建好的线程对象如t1 , t2 , t3 ,它们存在重复使用的问题
  • 就是说一个人用过了t1线程,t1线程还有可能被其他用户使用 , 这时如果你不关闭 , 别人拿到的就是你已经关闭的Connection对象

ThreadLocal的常用方法

方法名功能
public Object get()获取Map集合中当前线程对应的对象 (如Connection对象)
public void set(Object obj)把创建的对象存入Map集合中(如Connection对象)
public void remove()删除Map集合中当前线程对应的对象(如Connection对象)

使用ThreadLocal类优化事务

DBUtil⼯具类:将Connection对象存放到ThreadLocal里面的Map集合中, 保证service和dao中使⽤的Connection对象是同⼀个

public class DBUtil {private static ResourceBundle bundle = ResourceBundle.getBundle("resources/jdbc");private static String driver = bundle.getString("driver");private static String url = bundle.getString("url");private static String user = bundle.getString("user");private static String password = bundle.getString("password");// 工具类中的方法都是静态的,为了防止创建对象,故将构造方法私有化private DBUtil(){}// DBUtil类加载时注册驱动static {try {Class.forName(driver);} catch (ClassNotFoundException e) {e.printStackTrace();}}// 这个Map集合是全局的,在服务器中只有一个private static ThreadLocal<Connection> local = new ThreadLocal<>();//这里没有使用数据库连接池,直接创建连接对象public static Connection getConnection() throws SQLException {//获取当前线程对应的Connection对象,如果没有就创建并把它存入ThreadLocal类中的Map集合中Connection conn = local.get();if (conn == null) {conn = DriverManager.getConnection(url, user, password);local.set(conn);}return conn;}/*** 关闭资源* @param conn 连接对象* @param stmt 数据库操作对象* @param rs 结果集对象*/public static void close(Connection conn, Statement stmt, ResultSet rs){if (rs != null) {try {rs.close();} catch (SQLException e) {throw new RuntimeException(e);}}if (stmt != null) {try {stmt.close();} catch (SQLException e) {throw new RuntimeException(e);}}if (conn != null) {try {// 根本原因是:Tomcat服务器是支持线程池的,也就是说一个人用过了t1线程,t1线程还有可能被其他用户使用conn.close();local.remove();} catch (SQLException e) {throw new RuntimeException(e);}}}
}

不再接收service传过来的Connection对象 , 直接在AccountDao中获取当前线程对应的一个Connection对象

public class AccountDao {//插入账户信息public int insert(Account act) {PreparedStatement ps = null;int count = 0;try {//这里获取的Connection对象是从ThreadLocal中的Map集合中拿的(除了第一次是自己创建的)Connection conn = DBUtil.getConnection();//执行sql....} catch (SQLException e) {throw new RuntimeException(e);} finally {DBUtil.close(null, ps, null);}return count;}//根据主键删除账户public int deleteById(Long id){//执行sql...}//更新账户public int update(Account act) {//执行sql...}//根据账号查询账户public Account selectByActno(String actno){//执行sql...}//获取所有的账户public List<Account> selectAll() {//执行sql...}
}

相关文章:

ThreadLocal功能实现

模拟ThreadLocal功能实现 当前线程任意方法内操作连接对象 一个栈对应一个线程 , 一个方法调用另一个方法都是在一个线程内 , 只有执行了线程的start方法才会创建一个线程 定义一个Map集合 , key是当前线程(Thread.currentThread) , value是要绑定的数据(Connection对象) 以…...

Linux编辑器-vim使用

文章目录 前言一、vim编辑器1、vim的基本概念2、vim的基本操作2.1 命令模式切换至插入模式2.2 插入模式切换至命令模式2.3 命令模式切换至底行模式 3、vim命令模式命令集3.1 移动光标3.2 删除文字3.3 复制与粘贴3.4 替换3.5 撤销上一次操作3.6 更改3.7 跳至指定的行 4、vim末行…...

自助式数据分析平台:JVS智能BI功能介绍(二)数据集管理

数据集是JVS-智能BI中承载数据、使用数据、管理数据的基础&#xff0c;同样也是构建数据分析的基础。可以通俗地将其理解为数据库中的普通的表&#xff0c;他来源于智能的ETL数据加工工具&#xff0c;可以将数据集进行分析图表、统计报表、数字大屏、数据服务等制作。 在整体的…...

《5G技术引领教育信息化新革命》

5G技术引领教育信息化新革命 随着5G技术的快速发展&#xff0c;教育领域也迎来了全新的信息化时代。5G技术为教育行业提供了更高速、更稳定、更智能的网络连接&#xff0c;使得教育信息化不再局限于传统的课堂教学&#xff0c;而是延伸到了线上、线下的全时空教育。本文将详细介…...

cmake学习过程记录

目录 基础命令学习配置opencvcmake (Windows版本) 基础命令学习 //设置最低版本号 cmake_minimum_required(VERSION 3.5)//设置项目名称 project (hello_headers)//递归遍历文件夹src中的cpp文件放到变量SOURCES中 file(GLOB_RECURSE SOURCES src/*.cpp)//设置目标exe名称…...

Vue3、Vite使用 html2canvas 把Html生成canvas转成图片并保存,以及填坑记录

这两天接到新需求就是生成海报分享&#xff0c;生成的格式虽然是一样的但是自己一点点画显然是不符合我摸鱼人的性格&#xff0c;就找到了html2canvas插件&#xff0c;开始动工。 安装 npm install html2canvas --save文档 options 的参数都在里面按照自己需求使用 https://a…...

centos yum源配置(CentOS7 原生 yum 源修改为阿里 yum 源)

文章目录 centos yum源配置centos搭建内网yum源内网centos的yum软件源配置CentOS7 原生 yum 源修改为阿里 yum 源 centos yum源配置 centos搭建内网yum源 您好,在CentOS系统上搭建本地内网YUM仓库的方法如下: 安装httpd和createrepo工具 yum install httpd createrepo -y创…...

linux————ansible

一、认识自动化运维 自动化运维: 将日常IT运维中大量的重复性工作&#xff0c;小到简单的日常检查、配置变更和软件安装&#xff0c;大到整个变更流程的组织调度&#xff0c;由过去的手工执行转为自动化操作&#xff0c;从而减少乃至消除运维中的延迟&#xff0c;实现“零延时”…...

初识Java 8-1 接口和抽象类

目录 抽象类和抽象方法 接口定义 默认方法 多重继承 接口中的静态方法 作为接口的Instrument 本笔记参考自&#xff1a; 《On Java 中文版》 接口和抽象类提供了一种更加结构化的方式分离接口和实现。 抽象类和抽象方法 抽象类&#xff0c;其介于普通类和接口之间。在构…...

微信小程序音频后台播放功能

微信小程序在手机息屏后依旧能播放音频&#xff0c;需要使用 wx.getBackgroundAudioManager() 方法创建后台音乐播放器&#xff0c;并将音乐播放任务交给这个后台播放器。 具体实现步骤如下&#xff1a; 小程序页面中&#xff0c;使用 wx.getBackgroundAudioManager() 方法创…...

NotePad——xml格式化插件xml tools在线安装+离线安装

在使用NotePad时&#xff0c;在某些情形下&#xff0c;需要格式化Xml格式内容&#xff0c;可以使用Xml Tools插件。 一、在线安装 1. 打开Notepad 软件 2. 选择插件&#xff0c;选择“插件管理” 3. 搜索 XML Tools&#xff0c;找到该插件后&#xff0c;勾选该文件&#xff…...

图书管理系统 数据结构先导课暨C语言大作业复习 | JorbanS

问题描述 读取给定的图书文件book.txt中的信息&#xff08;book.txt中部分图书信息如下图所示&#xff09;&#xff0c;完成一个图书信息管理系统&#xff0c;该系统的各个功能模块要求利用菜单选项进行选择。 系统功能要求 图书浏览 读取book.txt中的文件信息并依次输出所…...

python 爬虫的开发环境配置

1、新建一个python项目 2、在控制台中分别安装下面三个包 pip install requests pip install beautifulsoup4 pip install selenium/ 如果安装时报以下错误&#xff1a; raise ReadTimeoutError(self._pool, None, "Read timed out.") pip._vendor.urllib3.exceptio…...

技术架构图是什么?和业务架构图的区别是什么?

技术架构图是什么&#xff1f; ​技术架构图是一种图形化工具&#xff0c;用于呈现软件、系统或应用程序的技术层面设计和结构。它展示了系统的各种技术组件、模块、服务以及它们之间的关系和交互方式。技术架构图关注系统内部的技术实现细节&#xff0c;以及各个技术组件之…...

数据增强

一、数据增强 当你训练一个机器学习模型时&#xff0c;你实际做工作的是调参&#xff0c;以便将特定的输入&#xff08;一副图像&#xff09;映像到输出&#xff08;标签&#xff09;。我们优化的目标是使模型的损失最小化&#xff0c; 以正确的方式调节优化参数即可实现这一目…...

【Unity】2D 对话模块的实现

对话模块主要参考 【Unity教程】剧情对话系统 实现。 在这次模块的构建将基于 unity ui 组件 和 C#代码实现一个从excel 文件中按照相应规则读取数据并展示的逻辑。这套代码不仅能实现正常的对话&#xff0c;也实现了对话中可以通过选择不同选项达到不同效果的分支对话功能。 …...

laravel安装初步使用学习 composer安装

一、什么是laravel框架 Laravel框架可以开发各种不同类型的项目&#xff0c;内容管理系统&#xff08;Content Management System&#xff0c;CMS&#xff09;是一种比较典型的项目&#xff0c;常见的网站类型&#xff08;如门户、新闻、博客、文章等&#xff09;都可以利用CM…...

【VS插件】VS code上的Remote - SSH

【VS插件】VS code上的Remote - SSH 目录 【VS插件】VS code上的Remote - SSH获得Linux服务器或者Linux系统的IP地址下载插件远程登录注意如果Linux虚拟机系统无法连接成功可能是没有开启ssh服务优势 作者&#xff1a;爱写代码的刚子 时间&#xff1a;2023.9.12 前言&#xff1…...

TensorFlow 02(张量)

一、张量 张量Tensor 张量是一个多维数组。与NumPy ndarray对象类似&#xff0c;tf.Tensor对象也具有数据类型和形状。如下图所示: 此外&#xff0c;tf.Tensors可以保留在GPU中。TensorFlow提供了丰富的操作库 (tf.add&#xff0c;tf.matmul,tf.linalg.inv等)&#xff0c;它们…...

513. 找树左下角的值

代码链接&#xff1a; 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 思路&#xff1a; 万金油层次遍历&#xff0c;保存每一层的第一个元素返回就行了 我的代码&#xff1a; /*** Definition for a binary tree node.* struct TreeNode {* …...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解

突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 ​安全措施依赖问题​ GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下&#xff0c;商品详情API作为连接电商平台与开发者、商家及用户的关键纽带&#xff0c;其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息&#xff08;如名称、价格、库存等&#xff09;的获取与展示&#xff0c;已难以满足市场对个性化、智能…...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了&#xff1a;一行…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强&#xff0c;React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 &#xff08;1&#xff09;使用React Native…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

在Ubuntu中设置开机自动运行(sudo)指令的指南

在Ubuntu系统中&#xff0c;有时需要在系统启动时自动执行某些命令&#xff0c;特别是需要 sudo权限的指令。为了实现这一功能&#xff0c;可以使用多种方法&#xff0c;包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法&#xff0c;并提供…...