最近一个项目中需要自己写个连接池, 写了一个下午,挺辛苦的,但不知道会不会出问题, 所以,贴到博客上,欢迎各路大神指点

1. 配置信息:

/**
*
*/
package cn.mjorcen.db.bean; import java.util.ResourceBundle; import org.apache.log4j.Logger; /**
*
* 配置信息
*
* @author mjorcen
* @email mjorcen@gmail.com
* @dateTime Oct 5, 2014 3:02:56 PM
* @version 1
*/
public class Configuration {
private ResourceBundle resource;
private Logger logger = Logger.getLogger(getClass());
private String driverClassName = "com.mysql.jdbc.Driver";
private String validationQuery = "SELECT 1";
private String url = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull";
private String user = "root";
private String password = "";
private int initialPoolSize = 3;
private int minPoolSize = 3;
private int maxPoolSize = 10;
private int maxStatements = 30;
private int maxIdleTime = 25000;
private int idleConnectionTestPeriod = 18000;
private int connectionLonger = 3600000; public Configuration() {
super(); } public Configuration(String _properties) {
super();
init(_properties);
} /**
*
* @param _properties
*
* @author mjorcen
* @email mjorcen@gmail.com
* @dateTime Oct 5, 2014 3:08:54 PM
* @version 1
*/
private void init(String _properties) {
resource = ResourceBundle.getBundle(_properties);
try {
String tmp = "";
setDriverClassName(resource.getString("driverClassName"));
setValidationQuery(resource.getString("validationQuery"));
setUrl(resource.getString("jdbc_url"));
setUser(resource.getString("jdbc_username"));
setPassword(resource.getString("jdbc_password")); tmp = resource.getString("initialPoolSize");
if (tmp != null) {
setInitialPoolSize(Integer.parseInt(tmp));
}
tmp = resource.getString("minPoolSize");
if (tmp != null) {
setMinPoolSize(Integer.parseInt(tmp));
}
tmp = resource.getString("maxPoolSize");
if (tmp != null) {
setMaxPoolSize(Integer.parseInt(tmp));
}
tmp = resource.getString("maxStatements");
if (tmp != null) {
setMaxStatements(Integer.parseInt(tmp));
}
tmp = resource.getString("maxIdleTime");
if (tmp != null) {
setMaxIdleTime(Integer.parseInt(tmp));
}
tmp = resource.getString("idleConnectionTestPeriod");
if (tmp != null) {
setIdleConnectionTestPeriod(Integer.parseInt(tmp));
}
tmp = resource.getString("connectionLonger");
if (tmp != null) {
setConnectionLonger(Integer.parseInt(tmp));
}
} catch (Exception e) {
e.printStackTrace();
logger.error(e);
} } public ResourceBundle getResource() {
return resource;
} public void setResource(ResourceBundle resource) {
this.resource = resource;
} public String getDriverClassName() {
return driverClassName;
} public void setDriverClassName(String driverClassName) {
this.driverClassName = driverClassName;
} public String getValidationQuery() {
return validationQuery;
} public void setValidationQuery(String validationQuery) {
this.validationQuery = validationQuery;
} public String getUrl() {
return url;
} public void setUrl(String url) {
this.url = url;
} public String getUser() {
return user;
} public void setUser(String user) {
this.user = user;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
} public int getInitialPoolSize() {
return initialPoolSize;
} public void setInitialPoolSize(int initialPoolSize) {
this.initialPoolSize = initialPoolSize;
} public int getMinPoolSize() {
return minPoolSize;
} public void setMinPoolSize(int minPoolSize) {
this.minPoolSize = minPoolSize;
} public int getMaxPoolSize() {
return maxPoolSize;
} public void setMaxPoolSize(int maxPoolSize) {
this.maxPoolSize = maxPoolSize;
} public int getMaxStatements() {
return maxStatements;
} public void setMaxStatements(int maxStatements) {
this.maxStatements = maxStatements;
} public int getMaxIdleTime() {
return maxIdleTime;
} public void setMaxIdleTime(int maxIdleTime) {
this.maxIdleTime = maxIdleTime;
} public int getIdleConnectionTestPeriod() {
return idleConnectionTestPeriod;
} public void setIdleConnectionTestPeriod(int idleConnectionTestPeriod) {
this.idleConnectionTestPeriod = idleConnectionTestPeriod;
} public int getConnectionLonger() {
return connectionLonger;
} public void setConnectionLonger(int connectionLonger) {
this.connectionLonger = connectionLonger;
} }

2. connection 的包装类, 因为mysql 一个连接连接8小时就会被mysql 干掉;所以出此下策;

/**
*
*/
package cn.mjorcen.db.bean; import java.sql.Connection;
import java.sql.SQLException;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger; import org.apache.log4j.Logger; /**
*
*
* @author mjorcen
* @email mjorcen@gmail.com
* @dateTime Oct 5, 2014 4:27:30 PM
* @version 1
*/
public class WarpConnection {
private Logger logger = Logger.getLogger(getClass());
static private AtomicInteger atomicInteger = new AtomicInteger(0);
private String name;
private long connectionTime;
private long lastWorkTime;
private Connection connection; public long getConnectionTime() {
return connectionTime;
} public void setConnectionTime(long connectionTime) {
this.connectionTime = connectionTime;
} public Connection getConnection() {
return connection;
} public void setConnection(Connection connection) {
this.connection = connection;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public static WarpConnection warp(Connection connection) {
WarpConnection warpConnection = new WarpConnection();
warpConnection.setConnection(connection);
warpConnection.setConnectionTime(System.currentTimeMillis());
warpConnection.setName("name" + atomicInteger.getAndAdd(1));
return warpConnection;
} public boolean isTimeOut(long time) {
boolean flag = System.currentTimeMillis() - this.connectionTime >= time;
System.out.println("name is " + this.name + " ,connectionTime is "
+ connectionTime + ", flag is " + flag + " ,time is "+time);
return flag;
} public long getLastWorkTime() {
return lastWorkTime;
} public void setLastWorkTime(long lastWorkTime) {
this.lastWorkTime = lastWorkTime;
} @Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((connection == null) ? 0 : connection.hashCode());
return result;
} @Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
WarpConnection other = (WarpConnection) obj;
if (connection == null) {
if (other.connection != null)
return false;
} else if (!connection.equals(other.connection))
return false;
return true;
} /**
* 查看链接是否有效
*
* @param connectionLonger
* 连接最大时间
* @return
*
* @author mjorcen
* @email mjorcen@gmail.com
* @dateTime Oct 5, 2014 5:21:07 PM
* @version 1600000
* @throws SQLException
*/
public boolean veryfiConnection(int connectionLonger) {
try { if (this.connection == null || this.connection.isClosed()
|| isTimeOut(connectionLonger)) {
return true;
}
} catch (SQLException e) {
e.printStackTrace();
}
return false;
}
}

3.连接池:

/**
*
*/
package cn.mjorcen.db.pool; import java.sql.Connection;
import java.sql.SQLException; /**
*
* 数据源最高级别接口,定义了数据源的基本功能
*
* @author mjorcen
* @email mjorcen@gmail.com
* @dateTime Oct 5, 2014 3:20:21 PM
* @version 1
*/
public interface PooledDataSource {
/**
* 获取链接
*
* @return
*
* @author mjorcen
* @email mjorcen@gmail.com
* @dateTime Oct 5, 2014 3:23:03 PM
* @version 1
* @throws SQLException
*/
Connection getConnection() throws Exception; /**
* 销毁
*
* @author mjorcen
* @email mjorcen@gmail.com
* @dateTime Oct 5, 2014 3:26:00 PM
* @version 1
*/
void destroy() throws Exception; /**
* 释放
*
* @param connection
*
* @author mjorcen
* @email mjorcen@gmail.com
* @dateTime Oct 5, 2014 3:27:09 PM
* @version 1
*/
void release(Connection connection) throws Exception; /**
* 数据源释放可用
*
* @return
*
* @author mjorcen
* @email mjorcen@gmail.com
* @dateTime Oct 5, 2014 3:28:15 PM
* @version 1
*/
boolean isAvailable(); }

一个简单的实现类如下:

/**
*
*/
package cn.mjorcen.db.pool.impl; import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; import cn.mjorcen.db.bean.Configuration;
import cn.mjorcen.db.bean.WarpConnection;
import cn.mjorcen.db.pool.PooledDataSource; /**
* 简单的线程池实现
*
* @author mjorcen
* @email mjorcen@gmail.com
* @dateTime Oct 5, 2014 3:24:32 PM
* @version 1
*/
public class AbstractPooledDataSource implements PooledDataSource { protected ConcurrentLinkedQueue<WarpConnection> idleQueue;
protected ConcurrentLinkedQueue<WarpConnection> busyQueue;
protected ThreadLocal<Connection> threadLocal;
protected AtomicInteger totalSize;
protected AtomicInteger currentSize;
protected boolean available;
protected Configuration configuration;
final Lock lock = new ReentrantLock();// 锁
// final Condition notFull = lock.newCondition(); // 实例化两个condition
final Condition notEmpty = lock.newCondition(); public AbstractPooledDataSource(Configuration configuration)
throws Exception {
super();
this.configuration = configuration;
idleQueue = new ConcurrentLinkedQueue<WarpConnection>();
busyQueue = new ConcurrentLinkedQueue<WarpConnection>();
threadLocal = new ThreadLocal<Connection>();
totalSize = new AtomicInteger(0);
currentSize = new AtomicInteger(0);
init();
} /**
*
*
* @author mjorcen
* @email mjorcen@gmail.com
* @dateTime Oct 5, 2014 3:49:36 PM
* @version 1
* @throws ClassNotFoundException
*/
private void init() throws Exception {
Class.forName("com.mysql.jdbc.Driver");
for (int i = 0; i < this.configuration.getInitialPoolSize(); i++) {
idleQueue.add(WarpConnection.warp(openConnection()));
}
this.totalSize.set(this.configuration.getInitialPoolSize());
available = true;
} protected Connection openConnection() throws SQLException {
return DriverManager.getConnection(configuration.getUrl(),
configuration.getUser(), configuration.getPassword());
} public Connection getConnection() throws SQLException {
Connection connection = threadLocal.get();
if (connection != null) {
return connection;
}
try {
lock.lock();
WarpConnection warpConnection = null;
try {
warpConnection = this.idleQueue.remove();
} catch (NoSuchElementException e) {
warpConnection = getWarpConnection();
}
veryfiConnection(warpConnection);
warpConnection.setLastWorkTime(System.currentTimeMillis());
this.busyQueue.add(warpConnection);
threadLocal.set(warpConnection.getConnection());
return warpConnection.getConnection();
} finally {
lock.unlock();
}
} /**
* 检查链接状态
*
* @author mjorcen
* @email mjorcen@gmail.com
* @dateTime Oct 5, 2014 5:17:06 PM
* @version 1
* @param warpConnection
* @throws SQLException
*/
private void veryfiConnection(WarpConnection warpConnection)
throws SQLException {
if (warpConnection.veryfiConnection(this.configuration
.getConnectionLonger())) {
warpConnection.setConnection(openConnection());
warpConnection.setConnectionTime(System.currentTimeMillis());
}
} /**
*
* @return
*
* @author mjorcen
* @email mjorcen@gmail.com
* @dateTime Oct 5, 2014 4:44:52 PM
* @version 1
* @throws SQLException
*/
private WarpConnection getWarpConnection() throws SQLException {
WarpConnection warpConnection = null; if (this.totalSize.get() < configuration.getMaxPoolSize()) {
warpConnection = WarpConnection.warp(openConnection());
this.totalSize.addAndGet(1);
return warpConnection;
}
while (true) {
try {
warpConnection = this.idleQueue.remove();
return warpConnection;
} catch (NoSuchElementException e) {
try {
this.notEmpty.wait();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
} } public void destroy() {
this.available = false;
ConcurrentLinkedQueue<WarpConnection> _idleQueue = this.idleQueue;
ConcurrentLinkedQueue<WarpConnection> _busyQueue = this.busyQueue;
this.idleQueue = null;
this.busyQueue = null;
this.threadLocal = null;
for (WarpConnection connection : _idleQueue) {
closeQuiet(connection.getConnection());
}
} private void closeQuiet(Connection connection) {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
} public void release(Connection connection) throws Exception {
try {
lock.lock();
if (this.available) {
WarpConnection warpConnection = null;
for (WarpConnection element : this.busyQueue) {
if (element.getConnection().equals(connection)) {
warpConnection = element;
break;
}
}
this.busyQueue.remove(warpConnection);
this.idleQueue.add(warpConnection);
// System.out.println("busyQueue = " + busyQueue.size());
// System.out.println("idleQueue = " + idleQueue.size());
threadLocal.set(null);
notEmpty.signal();// 一旦插入就唤醒取数据线程
} else {
closeQuiet(connection);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} public boolean isAvailable() {
return available;
} }

调用类:

/**
*
*/
package cn.mjorcen.db.test; import java.sql.Connection;
import java.sql.SQLException;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; import cn.mjorcen.db.bean.Configuration;
import cn.mjorcen.db.pool.impl.AbstractPooledDataSource; /**
*
*
* @author mjorcen
* @email mjorcen@gmail.com
* @dateTime Oct 5, 2014 4:00:09 PM
* @version 1
*/
public class Client {
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration("product_db");
final AbstractPooledDataSource dataSource = new AbstractPooledDataSource(
conf);
ExecutorService executor = Executors.newFixedThreadPool(10); Runnable r = new Runnable() {
public void run() {
try {
for (int i = 0; i < 3; i++) {
Connection connection = dataSource.getConnection();
System.out.println(Thread.currentThread().getName()
+ " : " + connection);
Thread.sleep(3000);
dataSource.release(connection);
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
for (int i = 0; i < 10; i++) { executor.execute(r);
}
// Connection connection = dataSource.getConnection();
// connection = dataSource.getConnection();
// System.out.println(connection);
// dataSource.release(connection);
}
}

配置文件:

driverClassName=com.mysql.jdbc.Driver
validationQuery=SELECT 1
jdbc_url=jdbc:mysql://115.29.36.149:3306/sai_zd?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
jdbc_username=c
jdbc_password=c
initialPoolSize=3
minPoolSize=3
maxPoolSize=10
maxStatements=30
maxIdleTime=25000
idleConnectionTestPeriod=18000
connectionLonger=3

java 连接池的简单实现的更多相关文章

  1. 几个主流java连接池

    池(Pool)技术在一定程度上可以明显优化服务器应用程序的性能,提高程序执行效率和降低系统资源开销.这里所说的池是一种广义上的池,比如数据库连接池.线程池.内存池.对象池等.其中,对象池可以看成保存对 ...

  2. 转载: 几个主流的Java连接池整理

    https://www.cnblogs.com/linjian/p/4831088.html 池(Pool)技术在一定程度上可以明显优化服务器应用程序的性能,提高程序执行效率和降低系统资源开销.这里所 ...

  3. 几个主流的Java连接池整理

    池(Pool)技术在一定程度上可以明显优化服务器应用程序的性能,提高程序执行效率和降低系统资源开销.这里所说的池是一种广义上的池,比如数据库连接池.线程池.内存池.对象池等.其中,对象池可以看成保存对 ...

  4. [JavaEE] 了解Java连接池

    转载自51CTO http://developer.51cto.com/art/201006/207768.htm 51CTO曾经为我们简单的介绍过Java连接池.要了解Java连接池我们先要了解数据 ...

  5. Okhttp之连接池ConnectionPool简单分析(一)

    开篇声明:由于本篇博文用到的一些观点或者结论在之前的博文中都已经分析过,所以本篇博文直接拿来用,建议读此博文的Monkey们按照下面的顺序读一下博主以下博文,以便于对此篇博文的理解: <Okht ...

  6. Java 连接池的工作原理(转)

    原文:Java 连接池的工作原理 什么是连接? 连接,是我们的编程语言与数据库交互的一种方式.我们经常会听到这么一句话“数据库连接很昂贵“. 有人接受这种说法,却不知道它的真正含义.因此,下面我将解释 ...

  7. Redis Java连接池调研

    Redis Java连接池调研 线上服务,由于压力大报错RedisTimeOut,但是需要定位到底问题出现在哪里? 查看Redis慢日志,slowlog get 发现耗时最大的也是11000us也就是 ...

  8. MySQL_(Java)【连接池】简单在JDBCUtils.java中创建连接池

    MySQL_(Java)[事物操作]使用JDBC模拟银行转账向数据库发起修改请求 传送门 MySQL_(Java)[连接池]使用DBCP简单模拟银行转账事物 传送门 Java应用程序访问数据库的过程: ...

  9. Java连接池详解

    于共享资源,有一个很著名的设计模式:资源池(Resource Pool).该模式正是为了解决资源的频繁分配﹑释放所造成的问题.为解决我们的问题,可以采用数据库连接池技术.数据库连接池的基本思想就是为数 ...

随机推荐

  1. jQuery中的选择器<思维导图>

    选择器是jQuery的重要组成部分,在jQuery中,对事件处理.遍历DOM和Ajax操作都依赖于选择器.如果能熟练地使用选择器,不仅能简化代码,而且可以达到事半功倍的效果. 下面是关于jQuery中 ...

  2. Ajax的ActionLink方法(适用于异步加载)

    8.2.1  AJAX的ActionLink方法 在Razor视图中,AJAX辅助方法可以通过Ajax属性访问.和HTML辅助方法类似,Ajax属性上的大部分AJAX辅助方法都是扩展方法(除了Ajax ...

  3. Codevs 1380 没有上司的舞会

    时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题目描述 Description Ural大学有N个职员,编号为1~N.他们有从属关系,也就是说他们的关系就 ...

  4. 【学习】Windows PE文件学习(一:导出表)

    今天做了一个读取PE文件导出表的小程序,用来学习. 参考了<Windows PE权威指南>一书. 首先, PE文件的全称是Portable Executable,可移植的可执行的文件,常见 ...

  5. activiti系列导读

    此用于管理activiti系列标签文章,activiti的分析是建立在目前最新的版本5.21之上. 官方指导手册链接:http://www.activiti.org/userguide/index.h ...

  6. ADO.NET笔记——使用连接池

    相关知识: 连接池的意义: 应用程序往往涉及大量的,并发的数据访问操作 数据库服务器能够同时维系的连接数量非常有限.如果某个数据库访问操作不及时关闭连接,就会减少其他调用对数据库访问的机会.因此,一般 ...

  7. 【Qt】Qt之重启应用程序【转】

    简介 今天分享的内容有些意思-如何重启一个应用程序.其实,有时候这是一个很重要的功能点,而且很人性化.易用性很好. 例如:切换用户.当某个用户登录成功之后,需要切换到其它账号,那么这时,你就知道它的重 ...

  8. 【PHP】phpcms 关联连接修复

    function _keylinks($txt, $replacenum = '',$link_mode = 1) { $keywords = $this->data['keywords']; ...

  9. 创建SQL数据库指定文件路径

    create database b2c on  primary  -- 默认就属于primary文件组,可省略(/*--数据文件的具体描述--*/    name='b2c',  -- 主数据文件的逻 ...

  10. 用python实现两个文本合并

    一段时间前在网上看到一段面试题,要求如下: employee文件中记录了工号和姓名 cat employee.txt: 100 Jason Smith 200 John Doe 300 Sanjay ...