首页 > 数据库技术 > 详细

java 简易版本数据库连接池

时间:2014-11-30 02:04:46      阅读:590      评论:0      收藏:0      [点我收藏+]

写了个 Java数据库连接池,具备基本的功能点:
  1、对池中活动连接的重用。
  2、池满时的适时等待。
  3、对空闲连接的适时关闭。

  抛砖引玉,走过路过,不吝赐教。

?

DBConnection.java如下:

?

package db;

import java.sql.Connection;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 封装的连接
 * @author Linkwork, 276247076@qq.com
 * @since 2014年11月01日
 */
public class DBConnection {
    
    /**
     * 原生的连接
     */
    private Connection connection = null;
    
    /**
     * 是否空闲
     */
    private AtomicBoolean idle = null;
    
    /**
     * 最近一次的空闲开始时间
     */
    private volatile long idleStart = 0L;
    
    /**
     * 标识
     */
    private int index = -1;
    
    /**
     * 构造函数
     * @param index 标识
     * @param connection 连接
     * @param idle 是否空闲
     */
    public DBConnection(int index, Connection connection, boolean idle) {
        this.index = index;
        this.connection = connection;
        this.idle = new AtomicBoolean(idle);
    }
    
    /**
     * 释放
     */
    public void release() {
        if (this.idle.compareAndSet(false, true)) {
            this.idleStart = System.currentTimeMillis();
        }
    }

    public Connection getConnection() {
        return connection;
    }

    public AtomicBoolean getIdle() {
        return idle;
    }
    
    public void setConnection(Connection connection) {
        this.connection = connection;
    }

    public int getIndex() {
        return index;
    }

    public long getIdleStart() {
        return idleStart;
    }

    public void setIdleStart(long idleStart) {
        this.idleStart = idleStart;
    }
    
}

?DBConnectionPool.java如下:

?

?

package db;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Vector;

/**
 * 数据库连接池
 * @author Linkwork, 276247076@qq.com
 * @since 2014年11月01日
 */
public class DBConnectionPool extends Thread {
    
    /**
     * 容量
     */
    private volatile int capacity = 1;
    
    /**
     * 驱动
     */
    private String driver = null;
    
    /**
     * 地址
     */
    private String url = null;
    
    /**
     * 用户名
     */
    private String user = null;
    
    /**
     * 密码
     */
    private String password = null;
    
    /**
     * 等待的轮询间隔
     */
    private volatile long waitInterval = 50L;
    
    /**
     * 等待的超时时间,默认 2分钟
     */
    private volatile long waitTimeout = 120000L;
    
    /**
     * 空闲的超时时间,默认 5分钟
     */
    private volatile long idleTimeout = 300000L;
    
    /**
     * 连接集
     */
    private Vector<DBConnection> dbconnectionLst = null;
    
    /**
     * 是否正在进行关闭
     */
    private volatile boolean closing = false;
    
    /**
     * 构造函数
     * @param capacity 容量
     * @param driver 驱动
     * @param url 地址
     * @param user 用户名
     * @param password 密码
     */
    public DBConnectionPool(
            int capacity,
            String driver,
            String url,
            String user,
            String password) {
        this.capacity = capacity;
        this.driver = driver;
        this.url = url;
        this.user = user;
        this.password = password;
        this.dbconnectionLst = new Vector<DBConnection>();
    }
    
    /**
     * 获取 DB连接
     * @return
     */
    public DBConnection getDBConnectionQuietly() {
        try {
            return this.getDBConnection();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    
    /**
     * 获取 DB连接
     * @return
     * @throws Exception
     */
    public DBConnection getDBConnection() throws Exception {
        long start = System.currentTimeMillis();
        // 当不是正在进行关闭
        while (! this.closing) {
            // 遍历连接集,获取空闲、可用的连接
            for (DBConnection dbconnection: this.dbconnectionLst) {
                if (dbconnection.getIdle().compareAndSet(true, false)) {
                    // 若连接未关闭
                    if (! this.isNullOrClose(dbconnection)) {
                        return dbconnection;
                    } else {
                        if (! this.closing) {
                            dbconnection.getIdle().set(true);
                        }
                    }
                }
            }
            // 若连接的总数未超出容量,则新建连接
            if ((this.dbconnectionLst.size() < this.capacity)
                    && (! this.closing)) {
                synchronized (this.dbconnectionLst) {
                    DBConnection dbconnection = this.createDBConnection(this.dbconnectionLst.size() + 1);
                    this.dbconnectionLst.add(dbconnection);
                    return dbconnection;
                }
            } 
            // 遍历连接集,重用空闲、不可用的连接
            for (DBConnection dbconnection: this.dbconnectionLst) {
                if (dbconnection.getIdle().compareAndSet(true, false)) {
                    // 若连接已关闭
                    if ((null == dbconnection.getConnection())
                            || dbconnection.getConnection().isClosed()) {
                        Connection connection = this.createConnection();
                        dbconnection.setConnection(connection);
                        return dbconnection;
                    } else if (! this.closing) {
                        dbconnection.getIdle().set(true);
                    }
                }
            }
            // 延迟轮询
            Thread.sleep(this.waitInterval);
            long end = System.currentTimeMillis();
            // 若等待超时
            if (end - start > this.waitTimeout) {
                throw new Exception("ERROR_WAIT_TIMEOUT");
            }
            start = end;
        } // while (! this.closing) {
        return null;
    }
    
    /**
     * 关闭连接池中的所有连接
     * @throws Exception
     */
    public void close() {
        this.closing = true;
        // 是否已经关闭
        boolean closed = false;
        // 当未关闭完成
        while (! closed) {
            closed = true;
            try {
                Thread.sleep(this.waitInterval);
            } catch (Exception e) {
                e.printStackTrace();
                return;
            }
            // 遍历连接集,关闭所有空闲连接
            for (DBConnection dbconnection: this.dbconnectionLst) {
                // 若连接空闲,则关闭该连接,并标记未关闭完成
                if (dbconnection.getIdle().compareAndSet(true, false)) {
                    closed = false;
                    try {
                        if (! this.isNullOrClose(dbconnection)) {
                            dbconnection.getConnection().close();
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        } // while (true) {
        System.out.println("has closed all!");
    }

    @Override
    public void run() {
        // 当不是正在进行关闭
        while (! this.closing) {
            try {
                // 延迟轮询
                Thread.sleep(this.waitInterval);
                // 遍历连接集,关闭空闲超时的连接
                for (DBConnection dbconnection: this.dbconnectionLst) {
                    // 若连接空闲,且空闲超时
                    if (dbconnection.getIdle().get()
                            && this.idleTimeout(dbconnection)
                            && dbconnection.getIdle().compareAndSet(true, false)) {
                        // 若连接空闲超时
                        if (this.idleTimeout(dbconnection)) {
                            dbconnection.setIdleStart(0L);
                            dbconnection.getConnection().close();
                            System.out.println("【dbconnection-" + dbconnection.getIndex() + "】idle timeout.");
                        }
                        if (! this.closing) {
                            dbconnection.getIdle().set(true);
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    public int getCapacity() {
        return capacity;
    }

    public void setCapacity(int capacity) {
        this.capacity = capacity;
    }

    public long getWaitTimeout() {
        return waitTimeout;
    }

    public void setWaitTimeout(long waitTimeout) {
        this.waitTimeout = waitTimeout;
    }

    public long getIdleTimeout() {
        return idleTimeout;
    }

    public void setIdleTimeout(long idleTimeout) {
        this.idleTimeout = idleTimeout;
    }

    public long getWaitInterval() {
        return waitInterval;
    }

    public void setWaitInterval(long waitInterval) {
        this.waitInterval = waitInterval;
    }

    /**
     * 创建 DB连接
     * @param index
     * @return
     * @throws Exception
     */
    private DBConnection createDBConnection(int index) throws Exception {
        return new DBConnection(index, this.createConnection(), false);
    }
    
    /**
     * 创建连接
     * @return
     * @throws Exception
     */
    private Connection createConnection() throws Exception {
        Class.forName(this.driver);
        return DriverManager.getConnection(this.url, this.user, this.password);
    }
    
    /**
     * DB连接是否空闲超时
     * @param dbconnection
     * @return
     */
    private boolean idleTimeout(DBConnection dbconnection) {
        return ((dbconnection.getIdleStart() > 0)
                && (System.currentTimeMillis() - dbconnection.getIdleStart() > this.idleTimeout));
    }
    
    /**
     * DB连接是否为空、或已关闭
     * @param dbconnection
     * @return
     * @throws SQLException
     */
    private boolean isNullOrClose(DBConnection dbconnection) throws SQLException {
        return ((null == dbconnection.getConnection())
                || dbconnection.getConnection().isClosed());
    }

}

?DBConnectionPoolTest.java如下

?

?

package db;

import java.sql.PreparedStatement;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 测试:数据库连接池
 * @author Linkwork, 276247076@qq.com
 * @since 2014年11月0日
 */
public class DBConnectionPoolTest {
    
    public static void main(String[] args) {
        DBConnectionPool pool = new DBConnectionPool(3, "com.mysql.jdbc.Driver", "jdbc:mysql://localhost:3306/db", "lw2013qq", "omg2056db4qq");
        pool.setWaitTimeout(10000L);
        pool.setIdleTimeout(40L);
        pool.start();
        testPool(pool);
        pool.close();
    }
    
    /**
     * 测试连接池
     * @param pool
     */
    public static void testPool(DBConnectionPool pool) {
        DBConnection dbconnection = pool.getDBConnectionQuietly();
        if (null != dbconnection) {
            try {
                // 创建表
                dbconnection.getConnection().prepareStatement("create table if not exists test_pool (tp_value int);").execute();
                dbconnection.release();
                mockConcurrent(pool);
                Thread.sleep(1000);
                mockConcurrent(pool);
                Thread.sleep(60);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                dbconnection.release();
            }
        }
    }
    
    /**
     * 模拟多线程并发访问数据库,并发插入 10行数据
     * @param pool
     */
    public static void mockConcurrent(DBConnectionPool pool) {
        for (int index = 0; index < 10; ++ index) {
            final int value = index;
            Thread thread = new Thread() {
                public void run() {
                    DBConnection dbconnection = pool.getDBConnectionQuietly();
                    if (null != dbconnection) {
                        try {
                            // 插入数据
                            PreparedStatement statement = dbconnection.getConnection().prepareStatement("insert into test_pool(tp_value) values(?);");
                            statement.setInt(1, value);
                            statement.execute();
                            StringBuffer msg = new StringBuffer();
                            msg.append("dbconnection index=").append(dbconnection.getIndex())
                                .append(", insert=").append(value)
                                .append(", time=").append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").format(new Date()));
                            System.out.println(msg.toString());
                        } catch (Exception e) {
                            e.printStackTrace();
                        } finally {
                            dbconnection.release();
                        }
                    }
                }
            };
            thread.start();
        }
    }

}

?运行 DBConnectionPoolTest.java,控制台输出:

?

dbconnection index=1, insert=0, time=2014-11-29 11:20:46 901

dbconnection index=2, insert=2, time=2014-11-29 11:20:46 917

dbconnection index=3, insert=8, time=2014-11-29 11:20:46 917

dbconnection index=2, insert=1, time=2014-11-29 11:20:46 960

dbconnection index=1, insert=4, time=2014-11-29 11:20:46 960

dbconnection index=3, insert=6, time=2014-11-29 11:20:46 984

dbconnection index=2, insert=7, time=2014-11-29 11:20:47 008

dbconnection index=1, insert=9, time=2014-11-29 11:20:47 008

【dbconnection-3】idle timeout.

dbconnection index=1, insert=3, time=2014-11-29 11:20:47 092

dbconnection index=2, insert=5, time=2014-11-29 11:20:47 142

【dbconnection-1】idle timeout.

【dbconnection-2】idle timeout.

dbconnection index=2, insert=1, time=2014-11-29 11:20:47 907

dbconnection index=1, insert=0, time=2014-11-29 11:20:47 929

dbconnection index=3, insert=3, time=2014-11-29 11:20:47 929

dbconnection index=2, insert=4, time=2014-11-29 11:20:47 948

dbconnection index=1, insert=5, time=2014-11-29 11:20:47 982

dbconnection index=3, insert=8, time=2014-11-29 11:20:47 982

?

has closed all!

?

?

bubuko.com,布布扣

欢迎大家访问我的个人网站 萌萌的IT人

java 简易版本数据库连接池

原文:http://aijuans.iteye.com/blog/2161821

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!