1、简介

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

2、为什么要用连接池

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

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<PoolConnection> 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();
} }
}

Oracle JDBC 连接池的更多相关文章

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

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

  2. 【JDBC&Dbutils】JDBC&JDBC连接池&DBUtils使用方法(重要)

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

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

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

  4. JDBC连接池-C池3P0连接

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

  5. JDBC连接池(三)DBCP连接池

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

  6. JDBC连接池-自定义连接池

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

  7. Jmeter(九)JDBC连接池

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

  8. jdbc连接池&改进dbUtil成C3P0Util

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

  9. Oracle JDBC连接服务名、SID和tnsnames.ora配置的多种方式

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

随机推荐

  1. VBA if...elseif...else语句

    一个If语句,后面可以跟一个或多个由布尔表达式组成的elseif语句,然后是一个默认的else语句,当所有条件变为false时执行else语句块. 语法 以下是VBScript中If...Elseif ...

  2. centos7安装google浏览器

    1. 配置yum源 在目录 /etc/yum.repos.d/ 下新建文件 google-chrome.repo cd /ect/yum.repos.d/ vim google-chrome.repo ...

  3. Android开发中常见问题分析及解决

    最近公司有新的业务需求,需要开发一款APP,因为我开发过Android APP(我想告诉他们,那是4年前的事了,嘤嘤嘤),就把开发任务交给我了,当然也不是我一个人啦,让我组开发小组,说白了,就是让我来 ...

  4. iOS中的分类(category)和类扩展(extension)

    今天在研究swift的时候看到了分类和扩展.这是两个十分重要有用的功能,但是之前用的不多,没有深入了解过,在今天就从头理一遍. 一.分类(Category): 概念: 分类(Category)是OC中 ...

  5. C++ 虚函数相关

    多态 C++的封装.继承和多态三大特性,封装没什么好说的,就是把事务属性和操作抽象成为类,在用类去实例化对象,从而对象可以使用操作/管理使用它的属性. 至于继承,和多态密不可分.基类可以进行派生,而派 ...

  6. 猫眼 top_100 爬取 ___只完成了第一页

    # python 3.7 from urllib.request import Request,urlopen import time,re,csv class Maoyan(object): def ...

  7. tornado 常见问题处理

    1 怎么获取从页面中的传值 使用 self.get_body_argument tornado的参数存储在self.request.body内,通过json以后就可以直接取值,当初我在前端使用angu ...

  8. C++自问

    1.forwarding reference 2.move 3. map的内部实现 rb tree,但rbtree优点是什么?使用情况?和b+有啥区别? 4.顺序容器和关联容器的区别: 本质区别是顺序 ...

  9. mount命令解析

    可以参考两位大神的理解 Linux mount 命令 Linux的mount命令详解

  10. 洛谷P5002 专心OI - 找祖先

    题目概括 题目描述 这个游戏会给出你一棵树,这棵树有\(N\)个节点,根结点是\(R\),系统会选中\(M\)个点\(P_1,P_2...P_M\). 要Imakf回答有多少组点对\((u_i,v_i ...