java 连接池的简单实现
最近一个项目中需要自己写个连接池, 写了一个下午,挺辛苦的,但不知道会不会出问题, 所以,贴到博客上,欢迎各路大神指点
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 连接池的简单实现的更多相关文章
- 几个主流java连接池
池(Pool)技术在一定程度上可以明显优化服务器应用程序的性能,提高程序执行效率和降低系统资源开销.这里所说的池是一种广义上的池,比如数据库连接池.线程池.内存池.对象池等.其中,对象池可以看成保存对 ...
- 转载: 几个主流的Java连接池整理
https://www.cnblogs.com/linjian/p/4831088.html 池(Pool)技术在一定程度上可以明显优化服务器应用程序的性能,提高程序执行效率和降低系统资源开销.这里所 ...
- 几个主流的Java连接池整理
池(Pool)技术在一定程度上可以明显优化服务器应用程序的性能,提高程序执行效率和降低系统资源开销.这里所说的池是一种广义上的池,比如数据库连接池.线程池.内存池.对象池等.其中,对象池可以看成保存对 ...
- [JavaEE] 了解Java连接池
转载自51CTO http://developer.51cto.com/art/201006/207768.htm 51CTO曾经为我们简单的介绍过Java连接池.要了解Java连接池我们先要了解数据 ...
- Okhttp之连接池ConnectionPool简单分析(一)
开篇声明:由于本篇博文用到的一些观点或者结论在之前的博文中都已经分析过,所以本篇博文直接拿来用,建议读此博文的Monkey们按照下面的顺序读一下博主以下博文,以便于对此篇博文的理解: <Okht ...
- Java 连接池的工作原理(转)
原文:Java 连接池的工作原理 什么是连接? 连接,是我们的编程语言与数据库交互的一种方式.我们经常会听到这么一句话“数据库连接很昂贵“. 有人接受这种说法,却不知道它的真正含义.因此,下面我将解释 ...
- Redis Java连接池调研
Redis Java连接池调研 线上服务,由于压力大报错RedisTimeOut,但是需要定位到底问题出现在哪里? 查看Redis慢日志,slowlog get 发现耗时最大的也是11000us也就是 ...
- MySQL_(Java)【连接池】简单在JDBCUtils.java中创建连接池
MySQL_(Java)[事物操作]使用JDBC模拟银行转账向数据库发起修改请求 传送门 MySQL_(Java)[连接池]使用DBCP简单模拟银行转账事物 传送门 Java应用程序访问数据库的过程: ...
- Java连接池详解
于共享资源,有一个很著名的设计模式:资源池(Resource Pool).该模式正是为了解决资源的频繁分配﹑释放所造成的问题.为解决我们的问题,可以采用数据库连接池技术.数据库连接池的基本思想就是为数 ...
随机推荐
- list转换成DataTable
list转换成DataTable类如下: public static DataTable ToDataTable<T>(this IList<T> datas) { DataT ...
- HTML的FORM的元素
form是是HTML的一个重要元素. form的常用控件有 单行文本框<input type="text" value="text" name=" ...
- DNS服务器搭建
注意正式运行的dns服务器主dns设置 中没有启用转发器,所以部分网页如taobao解析时可能很慢.开启转发器即可转发器地址指向电信dns. [root@master ~]# lsb_release ...
- 【学习笔记】【C语言】关键字
1.关键字就是C语言提供的有特殊含义的符号,也叫做“保留字” *C语言一共提供了32个关键字,这些关键字都被C语言赋予了特殊含义 auto double int struct break else l ...
- Java--CJDP
was定义,包定义, 1. Java的接口概念 进行封装,方便的使用 2. 包定义,Java 中多种包,进行迁移使用,包的导入,例如对数据库的操作Hibernate 3. 配置文件xml和json,对 ...
- Python深拷贝和浅拷贝
1- Python引用计数[1] 1.1 引用计数机制 引用计数是计算机编程语言中的一种内存管理技术,是指将资源(可以是对象.内存或磁盘空间等等)的被引用次数保存起来,当被引用次数变为零时就将其释放的 ...
- 《shell条件测试语句,字符串测试apache是否开启》
还得我想了10分钟才明白”!=“和"-n"的用法区别,做个笔记捋一捋 第一种方法:测试apache是否开启?字符串测试 #!/bin/bash web=`/usr/bin/pgre ...
- 清空系统日志shell scripts——自学笔记
这是一个清空系统日志的脚本: vim logmess_clean.sh #bin/bash //该脚本所使用的shell解释器 cd /var/log/ //切换到存放日志目录 ech ...
- 《搭建DNS内外网的解析服务》RHEL6
首先说下: 搭建的这个dns内外网的解析,是正向解析,反向解析自己根据正向解析把文件颠倒下就ok了 第一步我们先搭建一个DNS的正反向解析(参考上篇DNS正反向解析,这是上篇做过的) 第二部才是搭建内 ...
- Matlab2012a第一次安装打不开 查找程序安装类时出错
打开bin文件夹下的matlab!!!!!!进行激活~