多线程操作事务及手写连接池

版权声明:本文为博主原创文章,转载请注明出处:https://blog.csdn.net/qq_41922058

一、如何多线程操作事务

1.source

package jdbc;

import java.sql.Connection;

import java.sql.SQLException;

import java.sql.Statement;

public class Demo02 {

public Demo02() {

for (int i = 1; i <= 5; i++) {

new t().start();

}

} 

class t extends Thread {

public void run() {

System.err.println("1:获取连接");

Connection con = DsUtils.getCon();

System.err.println(con);

try {

System.err.println("2:设置事务提交方式");

con.setAutoCommit(false);

System.err.println("3:写入数据");

Statement st = con.createStatement();

String name = getName();

st.executeUpdate("insert into users values('景玺','" + name + "')");

// System.err.println("4:启动线程2");

           // t2.start();

// System.err.println("5:阻塞");

// new Scanner(System.in).nextLine();

 

System.err.println("4:提交数据");

con.commit();

} catch (SQLException e) {

e.printStackTrace();

} finally {

try {

con.setAutoCommit(true);

System.err.println("12:关闭连接");

con.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

};

};

//

// Thread t2 = new Thread() {

//

// public void run() {

//

// System.err.println("6:获取连接");

// Connection con = ConnUtils1.getCon();

// System.err.println(con);

// try {

// System.err.println("7:设置事务提交方式");

// con.setAutoCommit(false);

// System.err.println("8:写入数据");

// Statement st = con.createStatement();

// String name = getName()+","+con;

// st.executeUpdate("insert into users values('景玺','"+name+"')");

// System.err.println("9:提交数据");

// con.commit();

// } catch (SQLException e) {

// e.printStackTrace();

// } finally {

// try {

//

// System.err.println("10:关闭连接");

// con.close();

// } catch (SQLException e) {

// e.printStackTrace();

// }

// }

//

// };

// };

public static void main(String[] args) {

new Demo02();

}

}

2. 多线程操作事务存在的问题

假如只有一个con:多个线程进行操作事务,处理速度会非常的慢,管理不好con,则造成con关闭不能重用问题。

3. 解决思路

开发一个连接池,保存con并进行合适的管理

二、连接池原理

1. 实现多个连接的封装

第一步:private static List<Connection> list = new LinkedList<>();

声明linkedlist数据结构用于保存con,链表数据结构优点,能进行快速的增删数据

第二步:通过for循环创建多个con对象;

第三步:通过list.add(); 方法将con 保存到链表中;

第四步:创建getCon(); 方法获取返回con对象; 

package jdbc;

import java.sql.Connection;

import java.sql.DriverManager;

import java.util.LinkedList;

import java.util.List;

import java.util.Properties;

public class ConnUtils1 {

private static List<Connection> list = new LinkedList<>();

static {

try {

Properties pro = new Properties();

pro.load(ClassLoader.getSystemResourceAsStream("jdbc.properties"));

String driver = pro.getProperty("driver");

String url = pro.getProperty("url");

String name = pro.getProperty("name");

String psd = pro.getProperty("psd");

Class.forName(driver);

for(int i =1 ; i <= 3; i++ ) {

Connectioncon = DriverManager.getConnection(url, name, psd);

list.add(con);

}

} catch (Exception e) {

System.err.println("连接数据库异常");

}

}

public static Connection getCon() {

synchronized (list) {

if(list.size() == 0) {

try {

list.wait();

} catch (InterruptedException e) {

}

}

Connection con = list.remove(0);

return con;

}

}

}

2. 声明方法con使用完成进行归还

public static void backCon(Connection con) {

synchronized (list) {

list.add(con);

list.notify();

}

3. 增强close();

使用包装模式:实现A,并且含有A的成员变量

注意:包装模式需要实现接口当中的所有方法;

private static class MyConnection implements Connection{

private Connection mycon;

public MyConnection(Connection con) {

this.mycon = con;

}

@Override

public void close() throws SQLException { 

synchronized (list) {

list.add(this);

list.notify();

}

}

此时应该创建MyConnection对象进行包装con

MyConnection mycon = new MyConnection(con);

list.add(mycon);

当程序员调用con.close();时,连接不会关闭,而会向list进行归还con

三、开发标准连接池

1. 实现DataSource接口:

public class MyDataSource implements DataSource {}

2.实现接口中的getConnection方法

public class MyDataSource implements DataSource {

@Override

public Connection getConnection() throws SQLException {

synchronized (list) {

if (list.size() == 0) {

try {

list.wait();

} catch (InterruptedException e) {

}

}

Connection con = list.remove(0);

return con;

}

}

 

}

3.代码展示(只展示重要方法,不代表其他方法不需要实现)

package jdbc;

Import ...;

public class MyDataSource implements DataSource {

private List<Connection> list = new LinkedList<>();

public MyDataSource() {

try {

Properties pro = new Properties();

pro.load(ClassLoader.getSystemResourceAsStream("jdbc.properties"));

String driver = pro.getProperty("driver");

String url = pro.getProperty("url");

String name = pro.getProperty("name");

String psd = pro.getProperty("psd");

Class.forName(driver);

for (int i = 1; i <= 3; i++) {

Connection con = DriverManager.getConnection(url, name, psd);

MyConnection mycon = new MyConnection(con);

list.add(mycon);

}

} catch (Exception e) {

System.err.println("连接数据库异常");

}

}

@Override

public Connection getConnection() throws SQLException {

synchronized (list) {

if (list.size() == 0) {

try {

list.wait();

} catch (InterruptedException e) {

}

}

Connection con = list.remove(0);

return con;

}

}

private  class MyConnection implements Connection {

private Connection mycon;

public MyConnection(Connection con) {

this.mycon = con;

}

@Override

public void close() throws SQLException {

synchronized (list) {

list.add(this);

list.notify();

}

}

}

4.常用第三方连接池

C3P0

C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目HibernateSpring等。

DBCP

DBCPDataBase Connection Pool)数据库连接池,是java数据库连接池的一种,由Apache开发,通过数据库连接池,可以让程序自动管理数据库连接的释放和断开。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值