`

数据库连接池

阅读更多

连接工厂 ConnectionFactory

 

 

package myConnPool;

import java.util.LinkedHashSet;
import java.sql.*;
import java.util.Iterator;

public class ConnectionFactory {
	private static ConnectionFactory connFactory = null;
	private LinkedHashSet connPool = null;// 在使用的连接池
	private LinkedHashSet freeConnPool = null;// 空闲连接池
	private int maxConnCount = 4;//最大连接数
	private int minConnCount = 2;	// 最小连接数
	private int current_conn_count = 0;// 当前连接数
	private boolean isflag = false;// 是否创建工厂的标志
	private ConnectionFactory(){}
	public ConnectionFactory(ConnectionParam param) throws SQLException {
		if (connFactory == null) {
			synchronized (ConnectionFactory.class) {
				if (connFactory == null) {
					connFactory=new ConnectionFactory();
					connFactory.connPool = new LinkedHashSet();
					connFactory.freeConnPool = new LinkedHashSet();
					connFactory.maxConnCount = param.getMaxConn();
					connFactory.minConnCount = param.getMinConn();
					connFactory.isflag = true;
					try {// 初始化,创建minConnCount个连接
						for (int i = 0; i < connFactory.minConnCount; i++) {
							_Connection _conn = _Connection
									.getConnection(connFactory);
							connFactory.freeConnPool.add(_conn);// 加入空闲连接池
							connFactory.current_conn_count++;
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		}
	}
	// 标志工厂是否已经创建
	public boolean isCreate() {
		return connFactory.isflag;
	}
	
	/* 从连接池中取一个空闲的连接
	 * 	先遍历空闲连接池,看看是否有空闲连接
	 * 	如果能得到连接,得到连接后,从空闲连接池移除该链接,然后加入到当前连接池
	 * 判断连空闲连接池是否为空
	 *	如果空闲连接池为空,并且当前连接还没达到最大连接数,则创建新的连接,加入空闲连接池
	 *	然后检查当前连接池,把不再使用的连接归还给空闲连接池 
	 * 最后判断到底有没有得到连接
	 * 	如果没有得到连接,则再次遍历空闲连接池
	 */
	public synchronized Connection getFreeConnection() throws SQLException {
		Connection conn = null;
		Iterator iter = connFactory.freeConnPool.iterator();// 获取空闲连接
		while (iter.hasNext()) {
			_Connection _conn = (_Connection) iter.next();
			if (!_conn.isFree()) {// 找到未用连接
				conn = _conn.getFreeConnection();
				_conn.setIsFree(true);
				connFactory.freeConnPool.remove(_conn);// 移出空闲区
				connFactory.connPool.add(_conn);// 加入连接池
				break;
			}
		}
		// 检查空闲池是否为空
		if (connFactory.freeConnPool.isEmpty()) {
			// 再检查是否能够分配
			if (connFactory.current_conn_count < connFactory.maxConnCount) {
				int newcount = 0;
				// 取得要建立的数目
				if (connFactory.maxConnCount - connFactory.current_conn_count >= connFactory.minConnCount) {
					newcount = connFactory.minConnCount;
				} else {
					newcount = connFactory.maxConnCount
							- connFactory.current_conn_count;
				}
				for (int i = 0; i < newcount; i++) {// 创建连接
					_Connection _conn = _Connection.getConnection(connFactory);
					connFactory.freeConnPool.add(_conn);
					connFactory.current_conn_count++;
				}
			} else {// 如果不能新建,检查是否有已经归还的连接
				iter = connFactory.connPool.iterator();
				while (iter.hasNext()) {
					_Connection _conn = (_Connection) iter.next();
					if (!_conn.isFree()) {
						conn = _conn.getFreeConnection();
						_conn.setIsFree(false);
						connFactory.connPool.remove(_conn);
						connFactory.freeConnPool.add(_conn);
						break;
					}
				}
			}
		}
		// 再次检查是否能分配连接
		if (conn == null) {
			iter = connFactory.freeConnPool.iterator();
			while (iter.hasNext()) {
				_Connection _conn = (_Connection) iter.next();
				if (!_conn.isFree()) {
					conn = _conn.getFreeConnection();
					_conn.setIsFree(true);
					connFactory.freeConnPool.remove(_conn);
					connFactory.connPool.add(_conn);
					break;
				}
			}
			if (conn == null)// 如果不能则说明无连接可用
				throw new SQLException("没有可用的数据库连接");
		}
		System.out.println("get connection");
		return conn;
	}
	// 关闭该连接池中的所有数据库连接
	public synchronized void close() throws SQLException {
		this.isflag = false;
		SQLException excp = null;
		// 关闭空闲池
		Iterator iter = connFactory.freeConnPool.iterator();
		while (iter.hasNext()) {
			try {
				((_Connection) iter.next()).close();
				System.out.println("close connection:free");
				connFactory.current_conn_count--;
			} catch (Exception e) {
				if (e instanceof SQLException)
					excp = (SQLException) e;
			}
		}
		// 关闭在使用的连接池
		iter = connFactory.connPool.iterator();
		while (iter.hasNext()) {
			try {
				((_Connection) iter.next()).close();
				System.out.println("close connection:inused");
				connFactory.current_conn_count--;
			} catch (Exception e) {
				if (e instanceof SQLException)
					excp = (SQLException) e;
			}
		}
		if (excp != null)
			throw excp;
	}
}

 

数据连接代理类_Connection

 

package myConnPool;

import java.lang.reflect.*;
import java.sql.*;
//定义数据库连接的代理类
public class _Connection implements InvocationHandler {
	private Connection conn = null;// 定义连接
	private Statement statRef = null;// 定义监控连接创建的语句
	private PreparedStatement prestatRef = null;
	private boolean isFree = false;// 数据库的忙状态
	long lastAccessTime = 0;// 最后一次访问时间
	// 定义要接管的函数的名字
	String CREATESTATE = "createStatement";
	String CLOSE = "close";
	String PREPARESTATEMENT = "prepareStatement";
	private _Connection() {
		try {// 创建连接
			Class.forName(ConnectionParam.getInstance().getDriver())
					.newInstance();
			conn = DriverManager.getConnection(ConnectionParam.getInstance()
					.getUrl(), ConnectionParam.getInstance().getUser(),
					ConnectionParam.getInstance().getPassword());
			DatabaseMetaData dm = null;
			dm = conn.getMetaData();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		Object obj = null;
		// 判断是否调用了close的方法,如果调用close方法则把连接置为无用状态
		if (CLOSE.equals(method.getName())) {
			// 设置不使用标志
			setIsFree(false);
			// 检查是否有后续工作,清除该连接无用资源
			if (statRef != null)
				statRef.close();
			if (prestatRef != null)
				prestatRef.close();
			return null;
		}
		// 判断是使用了createStatement语句
		if (CREATESTATE.equals(method.getName())) {
			obj = method.invoke(conn, args);
			statRef = (Statement) obj;// 记录语句
			return obj;
		}
		// 判断是使用了prepareStatement语句
		if (PREPARESTATEMENT.equals(method.getName())) {
			obj = method.invoke(conn, args);
			prestatRef = (PreparedStatement) obj;
			return obj;
		}
		obj = method.invoke(conn, args);
		// 设置最后一次访问时间,以便及时清除超时的连接
		lastAccessTime = System.currentTimeMillis();
		return obj;
	}
	// 创建连接的工厂,只能让工厂调用
	static public _Connection getConnection(ConnectionFactory factory) {
		if (factory.isCreate()) {// 判断是否正确初始化的工厂
			_Connection _conn = new _Connection();
			return _conn;
		} else
			return null;
	}
	public Connection getFreeConnection() {
		// 返回数据库连接conn的接管类,以便截住close方法
		Connection conn2 = (Connection) Proxy.newProxyInstance(conn.getClass()
				.getClassLoader(), conn.getClass().getInterfaces(), this);
		return conn2;
	}

	// 该方法真正的关闭了数据库的连接

	void close() throws SQLException {
		// 由于类属性conn是没有被接管的连接,因此一旦调用close方法后就直接关闭连接
		conn.close();
	}

	public void setIsFree(boolean value) {
		isFree = value;
	}

	public boolean isFree() {
		return isFree;
	}
}

 

连接参数类 ConnectionParam

 

package myConnPool;

import java.io.Serializable;

public class ConnectionParam implements Serializable {
	private static ConnectionParam connParam=null;
	private String driver; // 数据库驱动程序
	private String url; // 数据连接的URL
	private String user; // 数据库用户名
	private String password; // 数据库密码
	private int MaxConnectionCount = 4;// 最大连接数
	private int MinConnectionCount = 2;// 最小连接数
	private ConnectionParam(){}
	public static ConnectionParam getInstance(){
		if(connParam==null){
			connParam=new ConnectionParam();
		}
		return connParam;
	}
	public String getDriver() {
		return driver;
	}
	public String getPassword() {
		return password;
	}
	public String getUrl() {
		return url;
	}
	public String getUser() {
		return user;
	}
	public int getMaxConn() {
		return this.MaxConnectionCount;
	}
	public int getMinConn() {
		return this.MinConnectionCount;
	}
	public void setDriver(String driver) {
		this.driver = driver;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public void setUrl(String url) {
		this.url = url;
	}
	public void setUser(String user) {
		this.user = user;
	}
	public void setMaxConn(int value) {
		this.MaxConnectionCount = value;
	}
	public void setMinConn(int value) {
		this.MinConnectionCount = value;
	}
}

 

 

测试类

 

package myConnPool;

import java.sql.*;

public class testmypool {
	
	public static void main(String[] args) {
		
		String user = "root";
		String password = "root";
		String driver = "com.mysql.jdbc.Driver";
		String url = "jdbc:mysql://localhost/authorization";
		ConnectionParam param = ConnectionParam.getInstance();
		param.setDriver(driver);
		param.setUrl(url);
		param.setUser(user);
		param.setPassword(password);
		param.setMaxConn(4);
		param.setMinConn(2);
		ConnectionFactory cf = null;
		try {
			cf = new ConnectionFactory(param);
			ConnectionFactory cf1 = new ConnectionFactory(param);
			Connection conn1 = null;
			long time = System.currentTimeMillis();
			for (int i = 0; i < 10; i++) {
				conn1 = cf.getFreeConnection();
				Statement stmt = conn1.createStatement();
				ResultSet rs = stmt.executeQuery("select * from function");
				if (rs.next()) {
					System.out.println("conn1 y");
				} else {
					System.out.println("conn1 n");
				}
				conn1.close();
			}
			System.out.println("pool:" + (System.currentTimeMillis() - time));
			time = System.currentTimeMillis();
			Class.forName(param.getDriver()).newInstance();
			for (int i = 0; i < 10; i++) {
				conn1 = DriverManager.getConnection(param.getUrl(), param
						.getUser(), param.getPassword());
				Statement stmt = conn1.createStatement();
				ResultSet rs = stmt.executeQuery("select * from function");
				if (rs.next()) {
					System.out.println("conn1 y");
				} else {
					System.out.println("conn1 n");
				}
				conn1.close();
			}
			System.out
					.println("no pool:" + (System.currentTimeMillis() - time));
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				cf.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics