虽然 J2EE 程序员一般都有现成的应用服务器所带的JDBC 数据库连接池,不过对于开发一般的 Java Application 、 Applet 或者 JSP、velocity 时,我们可用的JDBC 数据库连接池并不多,并且一般性能都不好。 Java 程序员都很羡慕 Windows ADO ,只需要 new Connection 就可以直接从数据库连接池中返回 Connection。并且 ADO Connection 是线程安全的,多个线程可以共用一个 Connection, 所以 ASP 程序一般都把 getConnection 放在 Global.asa 文件中,在 IIS 启动时建立数据库连接。ADO 的 Connection 和 Result 都有很好的缓冲,并且很容易使用。

其实我们可以自己写一个JDBC 数据库连接池。写 JDBC connection pool 的注意事项有:

1. 有一个简单的函数从连接池中得到一个 Connection。

2. close 函数必须将 connection 放回 数据库连接池。

3. 当数据库连接池中没有空闲的 connection,数据库连接池必须能够自动增加 connection 个数。

4. 当数据库连接池中的 connection 个数在某一个特别的时间变得很大,但是以后很长时间只用其中一小部分,应该可以自动将多余的 connection 关闭掉。

5. 如果可能,应该提供debug 信息报告没有关闭的 new Connection 。

如果要 new Connection 就可以直接从数据库连接池中返回 Connection, 可以这样写( Mediator pattern ) (以下代码中使用了中文全角空格):

public class EasyConnection implements java.sql.Connection{

private Connection m_delegate = null;

public EasyConnection(){

m_delegate = getConnectionFromPool();

}

public void close(){

putConnectionBackToPool(m_delegate);

}

public PreparedStatement prepareStatement(String sql) throws SQLException{

m_delegate.prepareStatement(sql);

}

//...... other method

}

看来并不难。不过不建议这种写法,因为应该尽量避免使用 Java Interface, 关于 Java Interface 的缺点我另外再写文章讨论。大家关注的是 Connection Pool 的实现方法。下面给出一种实现方法。

import java.sql.*;

import java.lang.reflect.*;

import java.util.*;

import java.io.*;

public class SimpleConnetionPool {

private static LinkedList m_notUsedConnection = new LinkedList();

private static HashSet m_usedUsedConnection = new HashSet();

private static String m_url = "";

private static String m_user = "";

private static String m_password = "";

static final boolean DEBUG = true;

static private long m_lastClearClosedConnection = System.currentTimeMillis();

public static long CHECK_CLOSED_CONNECTION_TIME = 4 * 60 * 60 * 1000; //4 hours

static {

initDriver();

}

private SimpleConnetionPool() {

}

private static void initDriver() {

Driver driver = null;

//load mysql driver

try {

driver = (Driver) Class.forName("com.mysql.jdbc.Driver").newInstance();

installDriver(driver);

} catch (Exception e) {

}

//load postgresql driver

try {

driver = (Driver) Class.forName("org.postgresql.Driver").newInstance();

installDriver(driver);

} catch (Exception e) {

}

}

public static void installDriver(Driver driver) {

try {

DriverManager.registerDriver(driver);

} catch (Exception e) {

e.printStackTrace();

}

}

public static synchronized Connection getConnection() {

clearClosedConnection();

while (m_notUsedConnection.size() > 0) {

try {

ConnectionWrapper wrapper = (ConnectionWrapper) m_notUsedConnection.removeFirst();

if (wrapper.connection.isClosed()) {

continue;

}

m_usedUsedConnection.add(wrapper);

if (DEBUG) {

wrapper.debugInfo = new Throwable("Connection initial statement");

}

return wrapper.connection;

} catch (Exception e) {

}

}

int newCount = getIncreasingConnectionCount();

LinkedList list = new LinkedList();

ConnectionWrapper wrapper = null;

for (int i = 0; i < newCount; i++) {

wrapper = getNewConnection();

if (wrapper != null) {

list.add(wrapper);

}

}

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

return null;

}

wrapper = (ConnectionWrapper) list.removeFirst();

m_usedUsedConnection.add(wrapper);

m_notUsedConnection.addAll(list);

list.clear();

return wrapper.connection;

}

private static ConnectionWrapper getNewConnection() {

try {

Connection con = DriverManager.getConnection(m_url, m_user, m_password);

ConnectionWrapper wrapper = new ConnectionWrapper(con);

return wrapper;

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

static synchronized void pushConnectionBackToPool(ConnectionWrapper con) {

boolean exist = m_usedUsedConnection.remove(con);

if (exist) {

m_notUsedConnection.addLast(con);

}

}

public static int close() {

int count = 0;

Iterator iterator = m_notUsedConnection.iterator();

while (iterator.hasNext()) {

try {

( (ConnectionWrapper) iterator.next()).close();

count++;

} catch (Exception e) {

}

}

m_notUsedConnection.clear();

iterator = m_usedUsedConnection.iterator();

while (iterator.hasNext()) {

try {

ConnectionWrapper wrapper = (ConnectionWrapper) iterator.next();

wrapper.close();

if (DEBUG) {

wrapper.debugInfo.printStackTrace();

}

count++;

} catch (Exception e) {

}

}

m_usedUsedConnection.clear();

return count;

}

private static void clearClosedConnection() {

long time = System.currentTimeMillis();

//sometimes user change system time,just return

if (time < m_lastClearClosedConnection) {

time = m_lastClearClosedConnection;

return;

}

//no need check very often

if (time - m_lastClearClosedConnection < CHECK_CLOSED_CONNECTION_TIME) {

return;

}

m_lastClearClosedConnection = time;

//begin check

Iterator iterator = m_notUsedConnection.iterator();

while (iterator.hasNext()) {

ConnectionWrapper wrapper = (ConnectionWrapper) iterator.next();

try {

if (wrapper.connection.isClosed()) {

iterator.remove();

}

} catch (Exception e) {

iterator.remove();

if (DEBUG) {

System.out.println("connection is closed, this connection initial StackTrace");

wrapper.debugInfo.printStackTrace();

}

}

}

//make connection pool size smaller if too big

int decrease = getDecreasingConnectionCount();

if (m_notUsedConnection.size() < decrease) {

return;

}

while (decrease-- > 0) {

ConnectionWrapper wrapper = (ConnectionWrapper) m_notUsedConnection.removeFirst();

try {

wrapper.connection.close();

} catch (Exception e) {

}

}

}

/**

* get increasing connection count, not just add 1 connection

* @return count

*/

public static int getIncreasingConnectionCount() {

int count = 1;

int current = getConnectionCount();

count = current / 4;

if (count < 1) {

count = 1;

}

return count;

}

/**

* get decreasing connection count, not just remove 1 connection

* @return count

*/

public static int getDecreasingConnectionCount() {

int count = 0;

int current = getConnectionCount();

if (current < 10) {

return 0;

}

return current / 3;

}

public synchronized static void printDebugMsg() {

printDebugMsg(System.out);

}

public synchronized static void printDebugMsg(PrintStream out) {

if (DEBUG == false) {

return;

}

StringBuffer msg = new StringBuffer();

msg.append("debug message in " + SimpleConnetionPool.class.getName());

msg.append("\r\n");

msg.append("total count is connection pool: " + getConnectionCount());

msg.append("\r\n");

msg.append("not used connection count: " + getNotUsedConnectionCount());

msg.append("\r\n");

msg.append("used connection, count: " + getUsedConnectionCount());

out.println(msg);

Iterator iterator = m_usedUsedConnection.iterator();

while (iterator.hasNext()) {

ConnectionWrapper wrapper = (ConnectionWrapper) iterator.next();

wrapper.debugInfo.printStackTrace(out);

}

out.println();

}

public static synchronized int getNotUsedConnectionCount() {

return m_notUsedConnection.size();

}

public static synchronized int getUsedConnectionCount() {

return m_usedUsedConnection.size();

}

public static synchronized int getConnectionCount() {

return m_notUsedConnection.size() + m_usedUsedConnection.size();

}

public static String getUrl() {

return m_url;

}

public static void setUrl(String url) {

if (url == null) {

return;

}

m_url = url.trim();

}

public static String getUser() {

return m_user;

}

public static void setUser(String user) {

if (user == null) {

return;

}

m_user = user.trim();

}

public static String getPassword() {

return m_password;

}

public static void setPassword(String password) {

if (password == null) {

return;

}

m_password = password.trim();

}

}

class ConnectionWrapper implements InvocationHandler {

private final static String CLOSE_METHOD_NAME = "close";

public Connection connection = null;

private Connection m_originConnection = null;

public long lastAccessTime = System.currentTimeMillis();

Throwable debugInfo = new Throwable("Connection initial statement");

ConnectionWrapper(Connection con) {

this.connection = (Connection) Proxy.newProxyInstance(

con.getClass().getClassLoader(),

con.getClass().getInterfaces(), this);

m_originConnection = con;

}

void close() throws SQLException {

m_originConnection.close();

}

public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {

Object obj = null;

if (CLOSE_METHOD_NAME.equals(m.getName())) {

SimpleConnetionPool.pushConnectionBackToPool(this);

}

else {

obj = m.invoke(m_originConnection, args);

}

lastAccessTime = System.currentTimeMillis();

return obj;

}

}

使用方法

public class TestConnectionPool{

public static void main(String[] args) {

SimpleConnetionPool.setUrl(DBTools.getDatabaseUrl());

SimpleConnetionPool.setUser(DBTools.getDatabaseUserName());

SimpleConnetionPool.setPassword(DBTools.getDatabasePassword());

Connection con = SimpleConnetionPool.getConnection();

Connection con1 = SimpleConnetionPool.getConnection();

Connection con2 = SimpleConnetionPool.getConnection();

//do something with con ...

try {

con.close();

} catch (Exception e) {}

try {

con1.close();

} catch (Exception e) {}

try {

con2.close();

} catch (Exception e) {}

con = SimpleConnetionPool.getConnection();

con1 = SimpleConnetionPool.getConnection();

try {

con1.close();

} catch (Exception e) {}

con2 = SimpleConnetionPool.getConnection();

SimpleConnetionPool.printDebugMsg();

}

}

运行测试程序后打印连接池中 Connection 状态,以及正在使用的没有关闭 Connection 信息。

java jdbc init_Java 的JDBC 数据库连接池实现方法相关推荐

  1. JDBC学习笔记03【JDBC事务管理、数据库连接池、JDBCTemplate】

    黑马程序员-JDBC文档(腾讯微云)JDBC笔记.pdf:https://share.weiyun.com/Kxy7LmRm JDBC学习笔记01[JDBC快速入门.JDBC各个类详解.JDBC之CR ...

  2. JDBC(11)—数据库连接池

    在实际开发过程中,特别是在web应用系统中,如果程序直接访问数据库中的数据,每一次数据访问请求丢必须经历建立数据库连接.打开数据库.存取数据和关闭数据库连接.而连接并打开数据库是一件既消费资源又费时的 ...

  3. JDBC核心技术六(数据库连接池)

    系列笔记目录 JDBC核心技术一(概述) JDBC核心技术二(获取数据库连接) JDBC核心技术三(PreparedStatement) JDBC核心技术四(Blob字段和批量插入) JDBC核心技术 ...

  4. spring 数据库 链接db2_Druid,Java语言中最好的数据库连接池

    Druid是Java语言中最好的数据库连接池,这话不是我说的,是Druid官方文档自己这样描述的,这是何等的自信! 连接池的作用,跟线程池的作用大同小异,都是为了减少频繁的创建销毁连接IO,提升性能. ...

  5. java jdbc close原理_JDBC数据库连接池原理

    JDBC是java数据库连接的简称.它是一种用于实行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用java语言编写的类和接口组成.其相关的API都在java.sql.*包下 ...

  6. 【JDBC】使用c3p0数据库连接池的各种报错警告

    使用c3p0数据库连接池的各种报错警告 使用c3p0数据库连接池的时候,先导入了三个jar包在lib 文件夹中, c3p0-0.9.5.2.jar mchange-commons-java-0.2.3 ...

  7. mysql jdbc批处理_JDBC批处理 数据库连接池

    关于JDBC Jdbc是java database connectivity的简称,java数据库连接,专门用来通过一段java代码连接数据库的一门技术. 使用方法大致为一下六个步骤: 一.注册驱动 ...

  8. Java Web 03 — JDBC_02(数据库连接池_C3P0_Druid、JdbcTemplate)

    文章目录 六:数据库连接池 6.1 概念 6.2 c3p0 6.3 Druid 6.4 DBCP(Apache) 6.5 DBUtils(快速创建对象,并以集合形式返回) 七.Spring JDBC ...

  9. 【java基础知识】编写数据库连接池

    之前一直用JDBC,现在接触到了DataSource.网上查到数据库连接池工具最好用的是Druid.下面分别介绍一下. 1.DataSource   数据源 什么是数据源: JDBC2.0提供了jav ...

最新文章

  1. FuzzyCMeans算法
  2. linux mysql配置文件修改编码,linux修改mysql字符集编码
  3. SPSS Modeler 报错
  4. php实现微信公众号群发消息接口(thinkphp3.2.3)
  5. 李彦宏PK马云:后发制人与厚积博发
  6. 深入医疗PACS影像融合存储解决方案
  7. 【Android -- 写作工具】Markdown 脚注尾注
  8. php中下载csv文件怎么打开,php – 下载csv文件
  9. 视频教程-VR 游戏创业中的那些坑-其他
  10. 穷和尚与富和尚的故事
  11. 中国联通(广东省分公司)研发技术初面
  12. RGB CMYK颜色理解及性质(1)
  13. 使用VScode简易编程
  14. i++与++i是什么意思?
  15. 用较新版本的Android Studio Chipmunk编译旧版本的Android 21的Sample
  16. 埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 A
  17. Currency Translation in Bex Query Variable 1
  18. matlab沪深a股量化投资培训班,MATLAB沪深A股量化投资培训班
  19. 【NodeJs-5天学习】第三天实战篇④ ——QQ机器人,实现自动回复、重要提醒
  20. 三角形面积外接圆内切圆

热门文章

  1. 试玩C++ 操作页面控件
  2. 在ACCESS中使用Group By语句
  3. 数据库高级知识——索引优化分析(二)
  4. 总结下载Spring Framework的jar包
  5. vlc 缓冲大小 设置_用libvlc 播放指定缓冲区中的视频流
  6. java中一个线程最小优先数_Java线程的优先级
  7. linux mysql安装_LINUX 安装 MYSQL
  8. oracle常见单词_Oracle中常见的英语单词
  9. python玩转android_如何用python玩跳一跳 ?(安卓版)
  10. 华为手机怎么使用读卡器_华为手机使用小窍门