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

ThreadLocal简单使用案例

        业务场景:保存业务数据表的时候,同时记录下日志。


import java.sql.Connection;
import java.sql.DriverManager;public class DBUtil {// 数据库配置private static final String driver = "com.mysql.jdbc.Driver";private static final String url = "jdbc:mysql://localhost:3306/test";private static final String username = "root";private static final String password = "root";private static Connection conn = null;public static Connection getDbConnection() {try {Class.forName(driver);conn = DriverManager.getConnection(url, username, password);} catch (Exception e) {e.printStackTrace();}return conn;}// 关闭数据库连接public static void closeDbConnection() {try {if (conn != null) {conn.close();}} catch (Exception e) {e.printStackTrace();}}
}

import com.example.springboottest.util.DBUtil;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.text.SimpleDateFormat;
import java.util.Date;public class ThreadLocalTest3 {private static final String UPDATE_SQL = "update t_test set num = ? where id = ?";private static final String INSERT_SQL = "insert into log (id, desc) values (?, ?)";public static void main(String[] args) {ThreadLocalTest3 service = new ThreadLocalTest3();service.updateBusiness(1, 3000);}public void updateBusiness(int id, int num) {try {// 获取连接Connection conn = DBUtil.getDbConnection();conn.setAutoCommit(false); // 关闭自动提交事务(开启事务)// 执行操作updateBizData(conn, UPDATE_SQL, id, num);// 插入日志insertLog(conn, INSERT_SQL, "描述"); // 提交事务conn.commit();} catch (Exception e) {e.printStackTrace();} finally {// 关闭连接DBUtil.closeDbConnection();}}private void updateBizData(Connection conn, String updateSQL, int id, int num) throws Exception {PreparedStatement pstmt = conn.prepareStatement(updateSQL);pstmt.setInt(1, id);pstmt.setLong(2, num);int rows = pstmt.executeUpdate();if (rows != 0) {System.out.println("业务数据更新成功!");}}private void insertLog(Connection conn, String insertSQL, String desc) throws Exception {PreparedStatement pstmt = conn.prepareStatement(insertSQL);pstmt.setString(1, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").format(new Date()));pstmt.setString(2, desc);int rows = pstmt.executeUpdate();if (rows != 0) {System.out.println("日志插入成功!");}}
}

        上面的代码直接运行肯定是没有问题的,但是如果在多线程下面去跑,就会报数据库连接关闭的错误。原因很简单,多线程下执行,可能一个线程刚获取到连接另一个线程就已经把连接关闭了,所以就会导致这样的问题,要解决这个问题,ThreaLocal就是一个很好的选择,只需要改调整下DBUtil里面获取连接的代码即可。如下代码所示:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;public class DBUtil {// 数据库配置private static final String driver = "com.mysql.jdbc.Driver";private static final String url = "jdbc:mysql://localhost:3306/test";private static final String username = "root";private static final String password = "root";private static ThreadLocal<Connection> connContainer = new ThreadLocal<Connection>(){//初始化connContainer里面的值,如果不重写则为null;@Overrideprotected Connection initialValue() {try {Class.forName(driver);return  DriverManager.getConnection(url, username, password);} catch (SQLException e) {throw new RuntimeException(e);}}};// 获取连接public static Connection getDbConnection() {Connection conn = connContainer.get();try {if (conn == null) {Class.forName(driver);conn = DriverManager.getConnection(url, username, password);}} catch (Exception e) {e.printStackTrace();} finally {connContainer.set(conn);}return conn;}// 关闭连接public static void closeDbConnection() {Connection conn = connContainer.get();try {if (conn != null) {conn.close();}} catch (Exception e) {e.printStackTrace();} finally {connContainer.remove();}}
}

http://www.lryc.cn/news/352101.html

相关文章:

  • 创建型设计模式之建造者模式
  • mainwindow 无菜单栏 可拖动,边界可扩大,动画浮现上边框
  • 机器学习云环境测试
  • 扩散模型自动管道AutoPipeline
  • Map六种遍历方式
  • 集合-1 数组ArrayListLinkedList
  • 42-1 应急响应之账户排查
  • Python3 笔记:sort() 和 sorted() 的区别
  • vue 引入 emoji 表情包
  • mysql 数据库 增量备份
  • SpringBoot之@Builder 注解
  • 云计算的能源消耗如何影响环境?
  • openwrt设置开机自启 tailscale为例
  • 副业树洞聊天项目/树洞倾诉/陪陪系统源码/树洞源码下载搭建
  • UWB论文:Introduction to Impulse Radio UWB Seamless Access Systems(2):脉冲;超宽带;测距;定位
  • Spring MVC/Web
  • C++中获取int最大与最小值(补)
  • 一个开源的工具类轮子是怎么造出来的
  • 零基础学Java第二十二天之迭代器 Iterator
  • 微服务架构-异步消息传递设计模式
  • 基于SSM的大学生兼职管理系统
  • leetcode刷题记录:前缀和
  • TENT: FULLY TEST-TIME ADAPTATION BY ENTROPY MINIMIZATION--论文笔记
  • Java期末复习指南(1):知识点总结+思维导图,考试速成!
  • OpenMV学习笔记1——IDE安装与起步
  • C++设计模式|结构型 适配器模式
  • 视频码流分析工具
  • 记一次重定向问题(浏览器安全)解决
  • 【传知代码】transformer-论文复现
  • 大模型日报|今日必读的 13 篇大模型论文