1、简介

数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。这项技术能明显提高对数据库操作的性能。

2、为什么要用连接池

如果按照单个连接来进行数据库操作,在高并发的情况下会导致数据库连接数耗尽的问题,而且单个连接的频繁创建和关闭,极大地增加了数据库的开销。针对这些,数据库连接池技术就能很好的解决这些问题。

dbutils python 关闭连接池 python oracle连接池_连接池

3、实现

定义连接对象

import java.sql.Connection;
/**
*
*/
public class PoolConnection {
private Connection connect;
//false 繁忙,true 空闲
private boolean status;
public PoolConnection() {
}
public PoolConnection(Connection connect, boolean status) {
this.connect = connect;
this.status = status;
}
public Connection getConnect() {
return connect;
}
public void setConnect(Connection connect) {
this.connect = connect;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
//释放连接池中的连接对象
public void releaseConnect(){
this.status = true;
}
}
定义一个接口获取连接对象
public interface DataSource {
PoolConnection getDataSource();
}
实现类
public class DataSourceImpl implements DataSource {
private ReentrantLock lock = new ReentrantLock();
//定义连接池中连接对象的存储容器
private List list = Collections.synchronizedList(new LinkedList<>());
//定义数据库连接属性
private final static String DRIVER_CLASS = PropertiesUtils.getInstance().getProperty("jdbc.driver_class");
private final static String URL = PropertiesUtils.getInstance().getProperty("jdbc.url");
private final static String USERNAME = PropertiesUtils.getInstance().getProperty("jdbc.username");
private final static String PASSWORD = PropertiesUtils.getInstance().getProperty("jdbc.password");
//定义默认连接池属性配置
private int initSize = 2;
private int maxSize = 4;
private int stepSize = 1;
private int timeout = 2000;
public DataSourceImpl() {
initPool();
}
//初始化连接池
private void initPool() {
String init = PropertiesUtils.getInstance().getProperty("initSize");
String step = PropertiesUtils.getInstance().getProperty("stepSize");
String max = PropertiesUtils.getInstance().getProperty("maxSize");
String time = PropertiesUtils.getInstance().getProperty("timeout");
initSize = init == null ? initSize : Integer.parseInt(init);
maxSize = max == null ? maxSize : Integer.parseInt(max);
stepSize = step == null ? stepSize : Integer.parseInt(step);
timeout = time == null ? timeout : Integer.parseInt(time);
try {
//加载驱动
Driver driver = (Driver) Class.forName(DRIVER_CLASS).newInstance();
//使用DriverManager注册驱动
DriverManager.registerDriver(driver);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public PoolConnection getDataSource() {
PoolConnection poolConnection = null;
try {
lock.lock();
//连接池对象为空时,初始化连接对象
if (list.size() == 0) {
createConnection(initSize);
}
//获取可用连接对象
poolConnection = getAvailableConnection();
//没有可用连接对象时,等待连接对象的释放或者创建新的连接对象使用
while (poolConnection == null) {
System.out.println("---------------等待连接---------------");
createConnection(stepSize);
poolConnection = getAvailableConnection();
if (poolConnection == null) {
TimeUnit.MILLISECONDS.sleep(30);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
return poolConnection;
}
//创建数据库连接
private void createConnection(int count) throws SQLException {
if (list.size() + count <= maxSize) {
for (int i = 0; i < count; i++) {
System.out.println("初始化了" + (i + 1) + "个连接");
Connection connect = DriverManager.getConnection(URL, USERNAME, PASSWORD);
PoolConnection pool = new PoolConnection(connect, true);
list.add(pool);
}
}
}
// 获取可用连接对象
private PoolConnection getAvailableConnection() throws SQLException {
for (PoolConnection pool : list) {
if (pool.isStatus()) {
Connection con = pool.getConnect();
// 验证连接是否超时
if (!con.isValid(timeout)) {
Connection connect = DriverManager.getConnection(URL, USERNAME, PASSWORD);
pool.setConnect(connect);
}
pool.setStatus(false);
return pool;
}
}
return null;
}
}
相关的PropertiesUtils 工具类
public class PropertiesUtils extends Properties {
private static final long serialVersionUID = 1L;
//定义属性文件名称
private final static String PROPERTY_FILE = "datasource.properties";
private static PropertiesUtils propertiesHolder = null;
private PropertiesUtils() {
if (propertiesHolder != null) {
throw new RuntimeException("此类是单例,已经存在实例化对象了。");
}
}
public static PropertiesUtils getInstance() {
if (propertiesHolder == null) {
synchronized (PropertiesUtils.class) {
if (propertiesHolder == null) {
propertiesHolder = new PropertiesUtils();
try (InputStream input = propertiesHolder.getClass().getClassLoader().getResourceAsStream(PROPERTY_FILE)) {
propertiesHolder.load(input);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
return propertiesHolder;
}
}
import java.sql.Connection;
/**
*
*/
public class PoolConnection {
private Connection connect;
//false 繁忙,true 空闲
private boolean status;
public PoolConnection() {
}
public PoolConnection(Connection connect, boolean status) {
this.connect = connect;
this.status = status;
}
public Connection getConnect() {
return connect;
}
public void setConnect(Connection connect) {
this.connect = connect;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
//释放连接池中的连接对象
public void releaseConnect(){
this.status = true;
}
}
定义一个接口获取连接对象
public interface DataSource {
PoolConnection getDataSource();
}
实现类
public class DataSourceImpl implements DataSource {
private ReentrantLock lock = new ReentrantLock();
//定义连接池中连接对象的存储容器
private List list = Collections.synchronizedList(new LinkedList<>());
//定义数据库连接属性
private final static String DRIVER_CLASS = PropertiesUtils.getInstance().getProperty("jdbc.driver_class");
private final static String URL = PropertiesUtils.getInstance().getProperty("jdbc.url");
private final static String USERNAME = PropertiesUtils.getInstance().getProperty("jdbc.username");
private final static String PASSWORD = PropertiesUtils.getInstance().getProperty("jdbc.password");
//定义默认连接池属性配置
private int initSize = 2;
private int maxSize = 4;
private int stepSize = 1;
private int timeout = 2000;
public DataSourceImpl() {
initPool();
}
//初始化连接池
private void initPool() {
String init = PropertiesUtils.getInstance().getProperty("initSize");
String step = PropertiesUtils.getInstance().getProperty("stepSize");
String max = PropertiesUtils.getInstance().getProperty("maxSize");
String time = PropertiesUtils.getInstance().getProperty("timeout");
initSize = init == null ? initSize : Integer.parseInt(init);
maxSize = max == null ? maxSize : Integer.parseInt(max);
stepSize = step == null ? stepSize : Integer.parseInt(step);
timeout = time == null ? timeout : Integer.parseInt(time);
try {
//加载驱动
Driver driver = (Driver) Class.forName(DRIVER_CLASS).newInstance();
//使用DriverManager注册驱动
DriverManager.registerDriver(driver);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public PoolConnection getDataSource() {
PoolConnection poolConnection = null;
try {
lock.lock();
//连接池对象为空时,初始化连接对象
if (list.size() == 0) {
createConnection(initSize);
}
//获取可用连接对象
poolConnection = getAvailableConnection();
//没有可用连接对象时,等待连接对象的释放或者创建新的连接对象使用
while (poolConnection == null) {
System.out.println("---------------等待连接---------------");
createConnection(stepSize);
poolConnection = getAvailableConnection();
if (poolConnection == null) {
TimeUnit.MILLISECONDS.sleep(30);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
return poolConnection;
}
//创建数据库连接
private void createConnection(int count) throws SQLException {
if (list.size() + count <= maxSize) {
for (int i = 0; i < count; i++) {
System.out.println("初始化了" + (i + 1) + "个连接");
Connection connect = DriverManager.getConnection(URL, USERNAME, PASSWORD);
PoolConnection pool = new PoolConnection(connect, true);
list.add(pool);
}
}
}
// 获取可用连接对象
private PoolConnection getAvailableConnection() throws SQLException {
for (PoolConnection pool : list) {
if (pool.isStatus()) {
Connection con = pool.getConnect();
// 验证连接是否超时
if (!con.isValid(timeout)) {
Connection connect = DriverManager.getConnection(URL, USERNAME, PASSWORD);
pool.setConnect(connect);
}
pool.setStatus(false);
return pool;
}
}
return null;
}
}
相关的PropertiesUtils 工具类
public class PropertiesUtils extends Properties {
private static final long serialVersionUID = 1L;
//定义属性文件名称
private final static String PROPERTY_FILE = "datasource.properties";
private static PropertiesUtils propertiesHolder = null;
private PropertiesUtils() {
if (propertiesHolder != null) {
throw new RuntimeException("此类是单例,已经存在实例化对象了。");
}
}
public static PropertiesUtils getInstance() {
if (propertiesHolder == null) {
synchronized (PropertiesUtils.class) {
if (propertiesHolder == null) {
propertiesHolder = new PropertiesUtils();
try (InputStream input = propertiesHolder.getClass().getClassLoader().getResourceAsStream(PROPERTY_FILE)) {
propertiesHolder.load(input);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
return propertiesHolder;
}
}

4、测试类

public class PoolTest
{
public static void main( String[] args )
{
DataSource source = new DataSourceImpl();
CountDownLatch latch = new CountDownLatch(3);
int i = 0;
for(; i < 3; i++){
new Thread(new Runnable() {
@Override
public void run() {
PreparedStatement pre = null;
ResultSet result = null;
try {
PoolConnection connect = source.getDataSource();
String sql = "select * from LEVEL4 where LEVEL4_CODE like ?";
pre = connect.getConnect().prepareCall(sql);
pre.setString(1, "%3AL34812ABAA%");
// 执行查询,注意括号中不需要再加参数
result = pre.executeQuery();
while (result.next()) {
// 当结果集不为空时
System.out.println("LEVEL4_CODE: " + result.getString("LEVEL4_CODE"));
}
TimeUnit.SECONDS.sleep(1);
connect.releaseConnect();
latch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}).start();
}
try {
latch.await();
System.out.println("-------结束-----------");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

四大流行的jdbc连接池之C3P0篇

C3P0是一个开放源代码的JDBC连接池,它在lib目录中与Hibernate一起发布,包括了实现jdbc3和jdbc2扩展规范说明的Connection 和Statement 池的DataSourc ...

【JDBC&amp&semi;Dbutils】JDBC&amp&semi;JDBC连接池&amp&semi;DBUtils使用方法&lpar;重要&rpar;

-----------------------JDBC---------- 0.      db.properties文件 driver=com.mysql.jdbc.Driver url=jdbc: ...

Spring&plus;SpringMVC&plus;MyBatis&plus;easyUI整合优化篇(九)数据层优化-jdbc连接池简述、druid简介

日常啰嗦 终于回到既定轨道上了,这一篇讲讲数据库连接池的相关知识,线程池以后有机会再结合项目单独写篇文章(自己给自己挖坑,不知道什么时候能填上),从这一篇文章开始到本阶段结束的文章都会围绕数据库和da ...

JDBC连接池-C池3P0连接

JDBC连接池-C3P0连接 c3p0连接池的学习英语好的看英文原版      c3p0 - JDBC3 Connection and Statement Pooling 使用c3p0连接池  三种方 ...

JDBC连接池&lpar;三&rpar;DBCP连接池

JDBC连接池(三)DBCP连接池 在前面的随笔中提到 了  1.JDBC自定义连接池  2. C3P0连接池 今天将介绍DBCP连接池 第一步要导入jar包   (注意:mysql和mysql 驱动 ...

JDBC连接池-自定义连接池

JDBC连接池 java JDBC连接中用到Connection   在每次对数据进行增删查改 都要 开启  .关闭  ,在实例开发项目中 ,浪费了很大的资源 ,以下是之前连接JDBC的案例 pack ...

Jmeter(九)JDBC连接池

JDBC为java访问数据库提供通用的API,可以为多种关系数据库提供统一访问.因为SQL是关系式数据库管理系统的标准语言,只要我们遵循SQL规范,那么我们写的代码既可以访问MySQL又可以访问SQL ...

jdbc连接池&amp&semi;改进dbUtil成C3P0Util

一.jdbc连接池 1.连接池的存在理由   前面介绍的dbUtils工具类虽然实现了一个对jdbc的简单封装.但它依旧采取从驱动管理获取连接 (DriverManager.getConnection ...

Oracle JDBC连接服务名、SID和tnsnames&period;ora配置的多种方式

昨天,领导安排去新服务器上部署项目,给了我数据库地址,服务名称,端口,用户名和密码.结果数据库一直连接不上,日志中的错误提示是监听未找到SID,我才明白原来我jdbc.properties中需要的是S ...

随机推荐

Surprise团队第三周项目总结

Surprise团队第二周项目总结 项目进展 这周我们小组的项目在上周的基础上进行了补充,主要注重在注册登录界面的实现,以及关于数据库的一些学习. 在设计注册登录界面时,每一块的地方控件都不一样,比如 ...

在Android中如何获取视频的第一帧图片并显示在一个ImageView中

String path  = Environment.getExternalStorageDirectory().getPath(); MediaMetadataRetriever media = n ...

28335timer

/*****************************************************************************Copyright: 2014,TkaiFi ...

Js使用word书签填充内容

Js使用word书签填充内容 1.在模板文件中需要填充的地方插入书签 填充内容为:(|光标所在处) 填写书签名,点击添加完成: 2.使用js打开模板,获取书签位置,填充数据: function pri ...

&lbrack;目录&rsqb;&lbrack;总结&rsqb; C&plus;&plus;和Java 中的主要操作对比

总结一些,C++ 和Java 中的一些常用操作对比,就当是自己的查询工具书啦.(暂时按随笔的更新时间排序) [Stack] c++ V.S. Java (2015.04.27) [Map]   c++ ...

《Java程序员面试笔试宝典》之volatile有什么作用

在由Java语言编写的程序中,有时候为了提高程序的运行效率,编译器会自动对其进行优化,把经常被访问的变量缓存起来,程序在读取这个变量的时候有可能会直接从缓存(例如寄存器)中来读取这个值,而不会去内存中 ...

escape和unescape给字符串编码

var before = "\xxx\xxx" var after = escape(before); var after2 = unescape(after );

iOS开发之NSObject的多线程

1.NSObject的多线程方法(用的时候要用@autoreleasepool{}包起来) 开启后台执行任务的方法: - (void)performSelectorInBackground:(SEL) ...

Java入门篇(二)——Java语言基础(上)

本篇我们开始进入Java的学习,首先在学习如何编写Java语言前要先了解Java程序的基本结构. 一.Java程序的基本结构 一个Java程序的基本结构大体可以分为包.类.main()主方法.标识符. ...