论坛首页 入门技术论坛

java数据库连接池实现

浏览 2048 次
该帖已经被评为新手帖
作者 正文
   发表时间:2010-02-05  
.package cc.vicp.eden.plug;   
.  
.import java.sql.*;   
.import java.util.*;   
.import java.lang.reflect.*;   
.  
./**  
. * 连接池类。  
. *   
. * @version 0.13  
. * @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 = 70;   
.        maxConn = 100;   
.        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++;   
.            System.out.println(Thread.currentThread().getName()   
.                    + " : getConnection" + "\ncurConn:" + curConn + "\npool:"  
.                    + pool.size() + "\n");   
.        }   
.        // 以连接的方式返回连接管理者对象   
.        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();   
.            // 是否调用了close方法?   
.            if (method.getName() == "close") {   
.                synchronized (pool) {   
.                    // 已使用连接数是否超出了最小连接数。   
.                    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;   
.    }   
.  
.    // /////////////////////////////////////////////////////////   
.    /* 其后部分为测试代码。 */  
.    private static final Object lock = new Object();   
.  
.    public static void main(String[] args) throws SQLException,   
.            InterruptedException {   
.        // 产生100个等待线程。   
.        for (int i = 0; i < 100; i++) {   
.            new Monitor("Monitor - " + i);   
.        }   
.        // 提供产生100个等待线程的等待时间(1秒)。   
.        Thread.sleep(1000);   
.        synchronized (cc.vicp.eden.plug.Monitor.lock) {   
.            // 同时唤醒所有线程。   
.            cc.vicp.eden.plug.Monitor.lock.notifyAll();   
.        }   
.        // 等待线程执行(5秒)。   
.        Thread.sleep(5000);   
.        // 答应最终剩余连接数以及连接池中的可用连接数。   
.        System.out.println("\n\n\nfinal curConn : " + curConn + "\nfinal pool : " + pool.size());   
.    }   
.}   
.  
./**  
. * 测试类。  
. *   
. * @author Eden  
. *   
. */  
.class Monitor extends Thread {   
.  
.    public static final Object lock = new Object();   
.  
.    private Connection conn;   
.    private static final Random random = new Random();   
.       
.       
.    public Monitor(String name) {   
.        this.setName(name);   
.        this.setPriority(Thread.MAX_PRIORITY);   
.        this.start();   
.    }   
.  
.    @Override  
.    public void run() {   
.        synchronized (lock) {   
.            try {   
.                System.out.println(this.getName() + " is ready!");   
.                lock.wait();   
.            } catch (InterruptedException e) {   
.                e.printStackTrace();   
.            }   
.        }   
.  
.        try {   
.            this.conn = ConnectionPool.getConnection();   
.        } catch (SQLException e) {   
.            e.printStackTrace();   
.        }   
.           
.        /*try {  
.            Thread.sleep(Math.abs(random.nextInt() % 3) + 1);  
.        } catch (InterruptedException e) {  
.            e.printStackTrace();  
.        }*/  
.           
.        try {   
.            conn.close();   
.        } catch (SQLException e) {   
.            e.printStackTrace();   
.        }   
.    }   
.}  

 

 

 

 

论坛首页 入门技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics