`
aijuans
  • 浏览: 1567804 次
社区版块
存档分类
最新评论

java 简易版本数据库连接池

阅读更多

写了个 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!

 

 

欢迎大家访问我的个人网站 萌萌的IT人
5
0
分享到:
评论

相关推荐

    Java实现数据库连接池简易教程

    Java实现数据库连接池简易教程主要涉及了如何在Java应用程序中创建并管理数据库连接池。数据库连接池是一种优化数据库操作的技术,通过复用已存在的数据库连接,减少频繁创建和关闭连接带来的性能开销。本文将介绍一...

    简易的数据库连接池实现

    自定义实现的数据库连接池,并进行加锁,保证线程安全,适合初学者学习。

    数据库连接池及其管理

    用java实现的简易的数据库连接池及其管理 课程设计 编写一关于Microsoft Access数据库连接池及其管理的相关类,要求能从XML配置文件中读取该数据库驱动程序,数据库名,连接池最大连接数,最多等待用户数,查询...

    Tomcat的数据库连接池设置与应用

    Tomcat作为一款广泛使用的Java应用服务器,其数据库连接池的正确配置对于提高系统性能、确保应用稳定运行至关重要。数据库连接池可以有效管理数据库连接资源,减少频繁创建和销毁数据库连接所带来的性能开销。本文将...

    纯手写简易版的数据库连接池jar包

    纯手写简易版的数据库连接池jar包

    JDBC的小Demo(基本的JDBC、数据库连接池、JDBCTemplate)

    关于使用JDBC的一些小Demo.主要是关于使用基本的JDBC进行增删改查操作,还有使用数据库连接池技术进行连接,最后写了几个关于JDBCTemplate的小Demo

    简易自带连接池的mysql操作工具,仅供学习。.zip

    4. **编程实现**:在Java中,可以通过JDBC(Java Database Connectivity)API来实现数据库连接池。例如,使用Apache的DBCP库,首先需要配置连接池的参数,如最大连接数、最小连接数、超时时间等,然后在程序中通过...

    连接池的简易实现demo

    本教程将通过一个简单的Java实现来探讨数据库连接池的工作原理和基本功能。 首先,我们需要理解数据库连接池的核心思想。连接池维护了一个预创建的数据库连接集合,当应用程序需要连接时,它不会每次都新建,而是从...

    简易连接池snappool.jar

    【简易连接池snappool.jar】是一个专门为Java应用程序设计的轻量级数据库连接池实现。在Java编程中,连接池是管理和复用数据库连接的一种高效技术,它避免了频繁创建和关闭数据库连接带来的性能开销,提升了应用的...

    java proxool轻量级数据池

    java proxool 轻量级数据库连接池配置文件,可进行简易的数据库连接操作

    j2ee连接池用法简易版

    在J2EE应用程序开发中,连接池是一种管理数据库连接的有效机制,它能够提高应用程序的性能和效率。连接池的基本思想是预先创建并维护一定数量的数据库连接,当应用程序需要时,可以从池中获取一个已存在的连接,使用...

    Java网上书城系统(简易版)

    数据库连接池是Java Web应用中管理数据库连接的一种技术,例如使用C3P0、Apache DBCP或HikariCP等库。它的主要目的是提高性能和效率,通过复用已建立的数据库连接,避免了频繁创建和销毁连接的开销。同时,连接池还...

    JAVA 简易图书借还管理

    - **数据库连接管理**:使用连接池管理数据库连接,提高系统性能,避免资源浪费。 3. **图形用户界面(GUI)** - **Swing库**:采用JAVA的Swing库构建用户界面,提供友好的交互体验,包括文本框、按钮、列表视图等...

    JAVA简易超市售货系统

    - **单例模式**:数据库连接池或全局配置可能使用单例模式,确保在整个应用中只有一个实例。 - **工厂模式**:可能用于创建对象,如商品实例或数据库连接对象。 通过学习和分析这个JAVA简易超市售货系统,学生...

    Java笔试面试题(含数据库&JQuery&JSP&JavaScript)

    数据库连接池是为了解决频繁地创建和销毁数据库连接所引起的性能问题。在启动时,连接池会预先建立一定数量的数据库连接,并维护一定数量的活跃连接。当客户端需要连接时,连接池会提供一个空闲连接,并将其标记为...

    数据集-使用java开发的一个简单数据库实现-优质项目分享.zip

    4. 设计模式:如单例模式用于数据库连接池的管理,工厂模式用于创建数据库连接等。 5. 架构设计:简单的MVC(Model-View-Controller)架构可能会被应用到,将业务逻辑、数据处理和用户界面分离。 根据提供的压缩...

    Java+Access实现简易通讯录

    8. **连接池**:在实际应用中,为了提高性能和资源利用率,可以使用连接池(如C3P0或HikariCP)来管理和复用数据库连接。 9. **事务管理**:对于多步骤的操作,如增删改联系人时,可能需要使用数据库事务确保数据...

    基于java 简易ORM 框架实现(一)

    接着,构建数据库连接池和事务管理器。最后,提供一套易于使用的API供用户进行数据操作。 通过理解这个简易ORM框架的实现,开发者不仅可以掌握ORM的基本工作原理,还能提升在Java数据库编程中的能力。实际项目中,...

    基于java 简易ORM 框架实现(二)

    在本篇“基于Java简易ORM框架实现(二)”中,我们将深入探讨如何构建一个简单的对象关系映射(Object-Relational Mapping,ORM)框架。ORM框架是Java开发中常用的一种技术,它允许开发者以面向对象的方式操作数据库,...

Global site tag (gtag.js) - Google Analytics