JDBCToolsV2:     利用ThreadLocal保证当前线程操作同一个数据库连接对象。

package com.dgd.test;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Properties; public class JDBCToolsV2 { private static DataSource ds;
private static ThreadLocal<Connection> th;
//静态代码块,创建数据库连接池
static {
try {
Properties p=new Properties();
p.load(JDBCToolsV1.class.getClassLoader().getResourceAsStream("druid.properties"));
ds= DruidDataSourceFactory.createDataSource(p);
th=new ThreadLocal<>();
} catch (Exception e) {
e.printStackTrace();
}
} public static Connection getConnection(){
//方式1: DriverManger.getConnection();
//方式2: 数据库连接池, ds.getConnection();
try {
Connection conn=th.get(); //获取当前线程的共享连接对象
if(conn==null) //当前线程没有拿过连接,第一个获取连接
{
conn=ds.getConnection();//从线程池中哪一个新的
th.set(conn); //放到当前线程共享变量中
}
return conn;
} catch (SQLException e) {
e.printStackTrace();
return null;
}
}
//关闭连接方法
public static void free( Connection conn){
try {
Connection conn=th.get();   //获取当前线程的共享连接对象
            if(conn!=null)              //当前线程获取连接
            {
                conn.close();      //关闭当前数据库连接
            }
       th.set(null);           //将ThreadLocal设置为空,防止上次关闭,下次获取一个关闭的数据库连接

} catch (SQLException e) {
e.printStackTrace();
}
} public static int update3( String sql, Object... args) throws SQLException {
Connection conn=getConnection();
PreparedStatement ps=conn.prepareStatement(sql);
if(args!=null && args.length>0)
{
for (int i = 0; i <args.length ; i++) {
ps.setObject(i+1,args[i]);
}
}
int len=ps.executeUpdate();
ps.close();
return len;
}
}

Test:

package com.dgd.test;

import org.junit.Test;

import java.sql.Connection;
import java.sql.SQLException; public class TestJDBCToolV1 { @Test
public void test2() throws SQLException {
String sql1="INSERT INTO COURSE VALUES(NULL,?)";
String sql2="INSERT INTO COURSE VALUES(NULL,?)";
Connection conn= JDBCToolsV2.getConnection(); conn.setAutoCommit(false);
try {
int len1=JDBCToolsV2.update3(sql1,"美术");
int len2=JDBCToolsV2.update3(sql2,"体育");
if(len1>0 && len2>0)
{
conn.commit();
}
else
{
conn.rollback();
}
} catch (SQLException e) {
conn.rollback();
}
conn.setAutoCommit(true);
JDBCToolsV2.free(conn); }
}

JDBCToolsV2:利用ThreadLocal保证当前线程操作同一个数据库连接对象。的更多相关文章

  1. Java多线程理解:线程安全的集合对象

    1.概念介绍 线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用.不会出现数据不一致或者数据污染. 线程不安全就 ...

  2. 多个线程怎样操作同一个epoll fd

    自己曾经做一个接口server时候,这样的场景下我的设计是多个线程操作同一个epoll fd.彼时,我的理由是epoll的系列函数是线程安全的. 当然有人不理解为什么会有多个线程操作同一个epoll ...

  3. 线程系列5--java中的ThreadLocal类实现线程范围内的数据共享(二)

    ThreadLocal类可以理解成一个类似与map集合使用,以当前线程当做key 来使用,将线程氛围内需要共享的数据当做value,形成键值对的形式使用.ThreadLocal和线程同步机制都是为了解 ...

  4. 8.12 day31 进程间通信 Queue队列使用 生产者消费者模型 线程理论 创建及对象属性方法 线程互斥锁 守护线程

    进程补充 进程通信 要想实现进程间通信,可以用管道或者队列 队列比管道更好用(队列自带管道和锁) 管道和队列的共同特点:数据只有一份,取完就没了 无法重复获取用一份数据 队列特点:先进先出 堆栈特点: ...

  5. python并发编程-进程间通信-Queue队列使用-生产者消费者模型-线程理论-创建及对象属性方法-线程互斥锁-守护线程-02

    目录 进程补充 进程通信前言 Queue队列的基本使用 通过Queue队列实现进程间通信(IPC机制) 生产者消费者模型 以做包子买包子为例实现当包子卖完了停止消费行为 线程 什么是线程 为什么要有线 ...

  6. java 多线程 线程安全及非线程安全的集合对象

    一.概念: 线程安全:就是当多线程访问时,采用了加锁的机制:即当一个线程访问该类的某个数据时,会对这个数据进行保护,其他线程不能对其访问,直到该线程读取完之后,其他线程才可以使用.防止出现数据不一致或 ...

  7. Java多线程操作同一个对象,线程不安全

    Java多线程操作同一个对象 发现问题:多个线程操作同一资源的情况下,线程不安全,数据紊乱 代码: package multithreading; // Java多线程操作同一个对象 // 买火车票的 ...

  8. 用ThreadLocal类实现线程安全的正确姿势

    大家通常知道,ThreadLocal类可以帮助我们实现线程的安全性,这个类能使线程中的某个值与保存值的对象关联起来.ThreadLocal提供了get与set等访问接口或方法,这些方法为每个使用该变量 ...

  9. VC中利用多线程技术实现线程之间的通信

    当前流行的Windows操作系统能同时运行几个程序(独立运行的程序又称之为进程),对于同一个程序,它又可以分成若干个独立的执行流,我们称之为线程,线程提供了多任务处理的能力.用进程和线程的观点来研究软 ...

随机推荐

  1. IDEA SpringBoot-Mybatis-plus 实现增删改查(CRUD)

    上一篇: IDEA SpringBoot-Mybatis实现增删改查(CRUD) 下一篇:Intellij IDEA 高效使用教程 (插件,实用技巧) 最好用的idea插件大全 一.前言 Mybati ...

  2. 二次封装这几个 element-ui 组件后,大大减少了我 CRUD 的时间

    element-ui 因其组件丰富.可拓展性强.文档详细等优点成为 Vue 最火的第三方 UI 框架.element-ui 其本身就针对后台系统设计了很多实用的组件,基本上满足了平时的开发需求. 既然 ...

  3. hadoop 运行测试

    hadoop集群运行 需要提前配置配置文件 slave节点用户得是hadoop,/usr/local/src的所有文件得属于hadoop 三台虚拟机关闭setenforce与防火墙,并且配置域名解析 ...

  4. [AcWing 798] 差分矩阵

    点击查看代码 #include<iostream> using namespace std; const int N = 1e3 + 10; int a[N][N], b[N][N]; v ...

  5. 简单的TRPG骰子

    又到了新一年的带团季了,今年准备用电脑来存放各种资料,自然也是需要一个简单的骰子工具了,反正也不复杂,就自己写了个,放着做个备份吧 主要功能是计算x1dy1+/-x2dy2+/-.....+/-con ...

  6. css实现气泡提示框三角及css中drop-shadow的使用

    css 做一个弹出气泡,样式怎么设计? 难点: 要实现白色三角型,可以在伪元素before和after上设置一个黑.一个白三角形,白三角形会挡住黑的,从而实现. &::before, & ...

  7. '@JvmDefault' is only supported since JVM target 1.8. Recompile with '-jvm-ta

    Java 1.8加入了接口默认实现的方式. 那么在kotlin中如何使用呢? 可以在方法上加注解@JvmDefault 但直接加上后会编译会碰到一些错误提示.下面是解决方法. 问题 Logcat 提示 ...

  8. python数据类型、用户交互和运算符

    基本数据类型 1.字典dict(dictionary) 能够准确的记录储存的信息 """ 大括号里面 放多个元素 之间用逗号隔开 元素为K:V键表示储存 K相对于V一般表 ...

  9. 对象、Map、Set、WeakMap、WeakSet

    对象.Map.Set.WeakMap.WeakSet 本文写于 2020 年 11 月 24 日 总的来说,Set 和 Map 主要的应用场景分别在于数据重组和数据储存.Set 是一种叫做「集合」的数 ...

  10. 696. Count Binary Substrings - LeetCode

    Question 696. Count Binary Substrings Example1 Input: "00110011" Output: 6 Explanation: Th ...