本连接池使用了代理模式,消除了油漆工那种繁琐的编码方式,本来嘛,只是修改一个close方法何必去实现整个Connection类。其中main函数中的Connection c11 = ConnectionPool.getConnection();将会报错(应为连接数超过了最大连接数),去掉改行本连接池将能正常运行了,由于注释比较详细,在这里就不多废话了,请个位看如下代码。
java 代码
- package cc.vicp.eden.plug;
- import java.sql.*;
- import java.util.*;
- import java.lang.reflect.*;
- /**
- * 连接池类。
- *
- * @version 0.12
- * @author Eden
- *
- */
- public abstract class ConnectionPool {
- /**
- * 连接池。
- */
- private static final LinkedList<ConnectionHandler> pool;
- /**
- * 最小连接数量,最大连接数量。
- */
- private static final int minConn, maxConn;
- /**
- * 当前连接数量。
- */
- private static int curConn;
- /**
- * 数据库的基本参数。
- */
- private static final String className, url, user, password;
- /**
- * 静态初始化。
- */
- static {
- // 初始化池。
- pool = new LinkedList<ConnectionHandler>();
- // 初始化基本连接信息。
- minConn = 3;
- maxConn = 10;
- curConn = 0;
- className = "com.mysql.jdbc.Driver";
- url = "jdbc:mysql://localhost/jforum";
- user = "root";
- password = "n8NrCwfj";
- // 加载数据库驱动。
- try {
- Class.forName(className);
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- }
- /**
- * 得到一个连接。
- *
- * @return 连接(Connection)对象。
- * @throws SQLException
- */
- public static Connection getConnection() throws SQLException {
- // 当前已经使用的连接是否达到或超出最大连接数?
- if (curConn >= maxConn)
- // 抛出连接用尽异常。
- throw new ConnectExhaustException();
- Connection conn = null;
- synchronized (pool) {
- // 连接池内的连接是否有可用连接?
- if (pool.size() > 0) {
- ConnectionHandler handler = null;
- // 得到一个连接管理者,并从连接池中移除。
- handler = pool.removeFirst();
- // 将该连接管理者设为可用。
- handler.enabled = true;
- // 创建一个连接管理者(以代理方式创建)。
- conn = (Connection) Proxy.newProxyInstance(handler.conn
- .getClass().getClassLoader(), handler.conn.getClass()
- .getInterfaces(), handler);
- } else {
- // 创建一个链接。
- conn = DriverManager.getConnection(url, user, password);
- // 创建一个连接管理者(以代理方式创建)。
- conn = (Connection) Proxy.newProxyInstance(conn.getClass()
- .getClassLoader(), conn.getClass().getInterfaces(),
- new ConnectionHandler(conn));
- }
- // 当前已使用连接数增加1。
- curConn++;
- }
- // 以连接的方式返回连接管理者对象
- return conn;
- }
- /**
- * 连接管理者类。
- *
- * @author Eden
- *
- */
- private static class ConnectionHandler implements InvocationHandler {
- /**
- * 连接是否可用。
- */
- private boolean enabled;
- /**
- * 连接(Connection)对象。
- */
- private Connection conn;
- /**
- * 构造器。
- *
- * @param conn
- * 连接(Connection)对象。
- *
- */
- public ConnectionHandler(Connection conn) {
- this.conn = conn;
- enabled = true;
- }
- /**
- * 代理方法,特别对于close方法进行了处理。
- */
- public Object invoke(Object proxy, Method method, Object[] args)
- throws Throwable {
- // 该连接管理者是否不可用?
- if (!enabled)
- // 抛出空指针异常
- throw new NullPointerException();
- synchronized (pool) {
- // 是否调用了close方法?
- if (method.getName() == "close") {
- // 已使用连接数是否超出了最小连接数。
- if (curConn > minConn) {
- // 关闭连接。
- conn.close();
- } else {
- // 将连接管理者设为不可用。
- this.enabled = false;
- // 将该连接返回连接池中。
- pool.add(this);
- }
- // 当前已使用连接数减少1。
- curConn--;
- System.out.println(Thread.currentThread().getName() + " : " + method.getName() + "\ncurConn:" + curConn + "\npool:" + pool.size() + "\n");
- // 返回一个空值。
- return null;
- }
- }
- // 正常调用连接的各种方法。
- return method.invoke(conn, args);
- }
- }
- /**
- * 连接用尽异常类。
- *
- * @author Eden
- *
- */
- private static final class ConnectExhaustException extends RuntimeException {
- /**
- * 版本序列号。
- */
- private static final long serialVersionUID = 0L;
- }
- public static void main(String[] args) throws SQLException,
- InterruptedException {
- for (int i = 0; i < 50; i++) {
- Connection conn = null;
- try {
- conn = getConnection();
- } catch (ConnectExhaustException e) {
- Thread.sleep(1000);
- i--;
- continue;
- }
- new Monitor(conn, "Monitor - " + i);
- }
- }
- }
- class Monitor extends Thread {
- private Connection conn;
- public Monitor(Connection conn, String name) {
- this.conn = conn;
- this.setName(name);
- this.start();
- }
- public void run() {
- try {
- Thread.sleep(10000);
- conn.close();
- } catch (SQLException e) {
- e.printStackTrace();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }