5、JAVA数据库连接池实现

转:http://greemranqq.iteye.com/blog/1969273
在一个成套的web系统中,不能更改源代码的情况下,要进行频繁的数据库操作,需要进行数据库连接管理而不影响原系统运行,这里就是一个java实现连接池的demo:
主要是对连接数的控制,比如最大20,最小2的连接。

package pool;
import java.sql.Connection;
import java.sql.SQLException;

public interface IConnectionPool {
// 获得连接
public Connection getConnection();
// 获得当前连接
public Connection getCurrentConnecton();
// 回收连接
public void releaseConn(Connection conn) throws SQLException;
// 销毁清空
public void destroy();
// 连接池是活动状态
public boolean isActive();
// 定时器,检查连接池
public void cheackPool();
}

package pool;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;

public class ConnectionPool implements IConnectionPool {
// 连接池配置属性
private DBbean dbBean;
private boolean isActive = false; // 连接池活动状态
private int contActive = 0;// 记录创建的总的连接数

// 空闲连接
private List<Connection> freeConnection = new Vector<Connection>();
// 活动连接
private List<Connection> activeConnection = new Vector<Connection>();
// 将线程和连接绑定,保证事务能统一执行
private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();

public ConnectionPool(DBbean dbBean) {
super();
this.dbBean = dbBean;
init();
cheackPool();
}

// 初始化
public void init() {
try {
Class.forName(dbBean.getDriverName());
for (int i = 0; i < dbBean.getInitConnections(); i++) {
Connection conn;
conn = newConnection();
// 初始化最小连接数
if (conn != null) {
freeConnection.add(conn);
contActive++;
}
}
isActive = true;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}

// 获得当前连接
public Connection getCurrentConnecton(){
// 默认线程里面取
Connection conn = threadLocal.get();
if(!isValid(conn)){
conn = getConnection();
}
return conn;
}

// 获得连接
public synchronized Connection getConnection() {
Connection conn = null;
try {
// 判断是否超过最大连接数限制
if(contActive < this.dbBean.getMaxActiveConnections()){
if (freeConnection.size() > 0) {
conn = freeConnection.get(0);
if (conn != null) {
threadLocal.set(conn);
}
freeConnection.remove(0);
} else {
conn = newConnection();
}

}else{
// 继续获得连接,直到从新获得连接
wait(this.dbBean.getConnTimeOut());
conn = getConnection();
}
if (isValid(conn)) {
activeConnection.add(conn);
contActive ++;
}
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return conn;
}

// 获得新连接
private synchronized Connection newConnection()
throws ClassNotFoundException, SQLException {
Connection conn = null;
if (dbBean != null) {
Class.forName(dbBean.getDriverName());
conn = DriverManager.getConnection(dbBean.getUrl(),
dbBean.getUserName(), dbBean.getPassword());
}
return conn;
}

// 释放连接
public synchronized void releaseConn(Connection conn) throws SQLException {
if (isValid(conn)&& !(freeConnection.size() > dbBean.getMaxConnections())) {
freeConnection.add(conn);
activeConnection.remove(conn);
contActive --;
threadLocal.remove();
// 唤醒所有正待等待的线程,去抢连接
notifyAll();
}
}

// 判断连接是否可用
private boolean isValid(Connection conn) {
try {
if (conn == null || conn.isClosed()) {
return false;
}
} catch (SQLException e) {
e.printStackTrace();
}
return true;
}

// 销毁连接池
public synchronized void destroy() {
for (Connection conn : freeConnection) {
try {
if (isValid(conn)) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
for (Connection conn : activeConnection) {
try {
if (isValid(conn)) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
isActive = false;
contActive = 0;
}

// 连接池状态
@Override
public boolean isActive() {
return isActive;
}

// 定时检查连接池情况
@Override
public void cheackPool() {
if(dbBean.isCheakPool()){
new Timer().schedule(new TimerTask() {
@Override
public void run() {
// 1.对线程里面的连接状态
// 2.连接池最小 最大连接数
// 3.其他状态进行检查,因为这里还需要写几个线程管理的类,暂时就不添加了
System.out.println("空线池连接数:"+freeConnection.size());
System.out.println("活动连接数::"+activeConnection.size());
System.out.println("总的连接数:"+contActive);
}
},dbBean.getLazyCheck(),dbBean.getPeriodCheck());
}
}
}

package pool;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Hashtable;
/**
* 连接管理类
* @author Ran
*
*/
public class ConnectionPoolManager {


// 连接池存放
public Hashtable<String,IConnectionPool> pools = new Hashtable<String, IConnectionPool>();

// 初始化
private ConnectionPoolManager(){
init();
}
// 单例实现
public static ConnectionPoolManager getInstance(){
return Singtonle.instance;
}
private static class Singtonle {
private static ConnectionPoolManager instance = new ConnectionPoolManager();
}


// 初始化所有的连接池
public void init(){
for(int i =0;i<DBInitInfo.beans.size();i++){
DBbean bean = DBInitInfo.beans.get(i);
ConnectionPool pool = new ConnectionPool(bean);
if(pool != null){
pools.put(bean.getPoolName(), pool);
System.out.println("Info:Init connection successed ->" +bean.getPoolName());
}
}
}

// 获得连接,根据连接池名字 获得连接
public Connection getConnection(String poolName){
Connection conn = null;
if(pools.size()>0 && pools.containsKey(poolName)){
conn = getPool(poolName).getConnection();
}else{
System.out.println("Error:Can't find this connecion pool ->"+poolName);
}
return conn;
}

// 关闭,回收连接
public void close(String poolName,Connection conn){
IConnectionPool pool = getPool(poolName);
try {
if(pool != null){
pool.releaseConn(conn);
}
} catch (SQLException e) {
System.out.println("连接池已经销毁");
e.printStackTrace();
}
}

// 清空连接池
public void destroy(String poolName){
IConnectionPool pool = getPool(poolName);
if(pool != null){
pool.destroy();
}
}

// 获得连接池
public IConnectionPool getPool(String poolName){
IConnectionPool pool = null;
if(pools.size() > 0){
pool = pools.get(poolName);
}
return pool;
}
}


package pool;

import java.util.ArrayList;
import java.util.List;
/**
* 初始化,模拟加载所有的配置文件
* @author Ran
*
*/
public class DBInitInfo {
public static List<DBbean> beans = null;
static{
beans = new ArrayList<DBbean>();
// 这里数据 可以从xml 等配置文件进行获取
// 为了测试,这里我直接写死
DBbean beanOracle = new DBbean();
beanOracle.setDriverName("oracle.jdbc.driver.OracleDriver");
beanOracle.setUrl("jdbc:oracle:thin:@7MEXGLUY95W1Y56:1521:orcl");
beanOracle.setUserName("mmsoa");
beanOracle.setPassword("password1234");

beanOracle.setMinConnections(5);
beanOracle.setMaxConnections(100);

beanOracle.setPoolName("testPool");
beans.add(beanOracle);
}
}


package pool;

import java.sql.Connection;
/**
* 模拟线程启动,去获得连接
* @author Ran
*
*/
public class ThreadConnection implements Runnable{
private IConnectionPool pool;
@Override
public void run() {
pool = ConnectionPoolManager.getInstance().getPool("testPool");
}

public Connection getConnection(){
Connection conn = null;
if(pool != null && pool.isActive()){
conn = pool.getConnection();
}
return conn;
}

public Connection getCurrentConnection(){
Connection conn = null;
if(pool != null && pool.isActive()){
conn = pool.getCurrentConnecton();
}
return conn;
}
}


package pool;



public class Client {
public static void main(String[] args) throws InterruptedException {
// 初始化连接池
Thread t = init();
t.start();
t.join();

ThreadConnection a = new ThreadConnection();
ThreadConnection b = new ThreadConnection();
ThreadConnection c = new ThreadConnection();
Thread t1 = new Thread(a);
Thread t2 = new Thread(b);
Thread t3 = new Thread(c);


// 设置优先级,先让初始化执行,模拟 线程池 先启动
// 这里仅仅表面控制了,因为即使t 线程先启动,也不能保证pool 初始化完成,为了简单模拟,这里先这样写了
t1.setPriority(10);
t2.setPriority(10);
t3.setPriority(10);
t1.start();
t2.start();
t3.start();

System.out.println("线程A-> "+a.getConnection());
System.out.println("线程B-> "+b.getConnection());
System.out.println("线程C-> "+c.getConnection());
}

// 初始化
public static Thread init() {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
IConnectionPool pool = initPool();
while(pool == null || !pool.isActive()){
pool = initPool();
}
}
});
return t;
}

public static IConnectionPool initPool(){
return ConnectionPoolManager.getInstance().getPool("testPool");
}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值