`
nmj1987
  • 浏览: 30275 次
  • 性别: Icon_minigender_1
  • 来自: 哈尔滨
文章分类
社区版块
存档分类
最新评论

有关数据库连接池的一些思考

阅读更多

以前写一些作业性质的网站,在对数据库操作时,都会写一个DBConnection类,用来获取数据库的连接,操作完数据之后,马上释放该连接。这是最简单的方法,但性能上是有很大问题的。比如我曾经用单线程循环1000次数据操作,就会出现异常。这时,使用连接池效果会好不少。下面的代码是在别人基础上稍加修改而来的。

以下是一个数据库连接池,启动时先从属性文件中读出一些参数,并启动最小连接数。有外来请求,就从连接池中移走一个对象。当前连接池大小为0时,参考最大连接数,新建若干个链接。当连接数超出最大限制时,则不再新建连接,这时如果有新的连接请求,而连接池目前又没有空闲的连接的话,那就很抱歉,只能返回空了。(返回空必然会引发异常,这不是我们所希望看到的。谁如果有好的解决方案,望告知)。

ConnectionPool.java

import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import java.util.Vector;

public class ConnectionPool {

    private Vector<Connection> pool;

    private String url;

    private String username;

    private String password;

    private String driverClassName;

    /** 
     * 连接池的大小,也就是连接池中有多少个数据库连接。
     */
    private int poolSize;
    
    private int poolSizeMax;

    private static ConnectionPool instance = new ConnectionPool();

    private ConnectionManager connectionManager;
    /** 
     * 私有的构造方法,禁止外部创建本类的对象,要想获得本类的对象,通过<code>getIstance</code>方法。
     * 使用了设计模式中的单子模式。
     */
    private ConnectionPool() {
        init();
    }

    /** 
     * 连接池初始化方法,读取属性文件的内容 建立连接池中的初始连接
     */
    private void init() {
        pool = new Vector<Connection>();
        readConfig();
        addConnection(poolSize);
        connectionManager = new ConnectionManager(pool);
        connectionManager.start();
    }

    /** 
     * 返回连接到连接池中
     */
    public synchronized void release(Connection conn) {
        pool.add(conn);

    }

    /** 
     * 关闭连接池中的所有数据库连接
     */
    public synchronized void closePool() {
        for (int i = 0; i < pool.size(); i++) {
            try {
                ((Connection) pool.get(i)).close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            pool.remove(i);
        }
    }

    /** 
     * 返回当前连接池的一个对象
     */
    public static ConnectionPool getInstance() {
        return instance;
    }

    /** 
     * 返回连接池中的一个数据库连接
     */
    public synchronized Connection getConnection() { 
    	Connection conn;
        if (pool.size() <= 0) {
              if(poolSize<=(poolSizeMax>>2)) {
        		addConnection(poolSize);
        		poolSize<<=2;	
        	}
        	else if(poolSize<poolSizeMax){
        		addConnection(poolSize);
            	poolSize=poolSizeMax; 	
        	}
        }
        conn = pool.remove(0);//pool.get(0),pool的size并不会减1
    	return conn;
    }

    /** 
     * 在连接池中创建初始设置的的数据库连接
     */
    private void addConnection(int size) {
        Connection conn = null;
        for (int i = 0; i < size; i++) {

            try {
                Class.forName(driverClassName);
                conn = java.sql.DriverManager.getConnection(url, username, password);
                pool.add(conn);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            }

        }
    }

    /** 
     * 读取设置连接池的属性文件
     */
    private void readConfig() {
        try {
            String path = System.getProperty("user.dir") + "\\dbpool.properties";
            FileInputStream is = new FileInputStream(path);
            Properties props = new Properties();
            props.load(is);
            this.driverClassName = props.getProperty("driverClassName");
            this.username = props.getProperty("username");
            this.password = props.getProperty("password");
            this.url = props.getProperty("url");
            this.poolSize = Integer.parseInt(props.getProperty("poolSizeMin"));
            this.poolSizeMax = Integer.parseInt(props.getProperty("poolSizeMax"));
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("读取属性文件出错. ");        
        }
    }
}

 连接池的大小应该根据系统的空闲状况灵活的改变连接的数量。比如请求高峰到来时,池中的连接数可能已经到了最大值,系统总是维持这么多的连接是很消耗资源的,因此应该有一个机制不断地减小连接。当然,这需要用到线程。

ConnectionManager.java

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

public class ConnectionManager extends Thread{
	
	/*连接池最小的链接数量*/
	public static int MIN_SIZE = 3;
	
    private Vector<Connection> pool;
	
	public ConnectionManager(Vector<Connection> pool)
	{
		this.pool = pool;
	}
	
	public void run() 
	{
		while(pool.size()>MIN_SIZE)  
		{
			pool.setSize(pool.size()-1);
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

 

下面是连接数据库的属性文件

driverClassName=com.microsoft.jdbc.sqlserver.SQLServerDriver
username=sa
password=123456
url=jdbc:microsoft:sqlserver://localhost:1433/estore
poolSizeMax=10
poolSizeMin=3

 

最后,我同时用了3个线程来不断地获取连接,测试结果表明,使用连接池之后,效率提高了100%。而且,如果线程越多,连接池的优势将更加明显。

3
0
分享到:
评论
3 楼 wh8766 2009-03-08  
恩 了解了~
3Q3Q
2 楼 nmj1987 2009-03-08  
最近看《java服务器高级编程》,里面提到数据库连接池,我这个属于传统的连接池,现在已经很少用了。getConnection() 的流程是这样的,初始化的时候不是建立了3个连接吗,一个用户来申请,占用一个,只剩两个了,那么pool.size()就等于2了。又分别来两个用户连接,size等于0了。如果在这三个用户释放连接前,又有新的连接请求,只要poolSize小于poolSizeMax的一半,那么就把poolSize翻倍,变成6。当6个连接有被用完了,但poolSize大于于poolSizeMax的一半,那就只好把poolSize扩大到poolSizeMax了。
1 楼 wh8766 2009-03-07  
思想上是理解了
有点地方看的晕乎,博主能给解释下么
getConnection() 的流程,谢谢
最近也在看数据库连接池的东西,没自己写直接用的Proxool组件……

相关推荐

    关于数据库连接池的问题和思考

    近数据中心出了一些问题,在Mysql连接上...  数据库有自己的连接池,例如Mysql,当一种编程语言要使用Mysql数据库时,Mysql公司会编写这种语言的数据库驱动,例如vb.net的Mysql驱动,所以,当vb.net连接mysql时,mys

    JAVA与数据库实训项目实习感想心得体会9篇范文

    在实训项目中,我们还接触到了数据库连接池的概念,如Apache的DBCP或C3P0,它们可以有效地管理数据库连接,提高系统性能。同时,JDBC(Java数据库连接)是连接JAVA应用和数据库的重要桥梁,我们学习了如何编写DAO...

    从零开始MySQL PDF资源

    常见的数据库连接池有DBCP、C3P0、Druid等等,大家如果有兴趣的话,可以去搜索一下数据库连接池的使用例子和代码,甚或探索一下数据库连接池的底层原理,但这个不是我们专栏的重点,我们就不会拓展了。毕竟我们专栏...

    使用Java实现数据库编程整本书代码和PPT

    7. **连接池**:在实际应用中,使用连接池(如C3P0、HikariCP或Apache DBCP)管理数据库连接,可以有效提高系统性能并减少资源浪费。 8. **ORM框架**:为了简化数据库操作,Java有许多Object-Relational Mapping ...

    accp5.0 使用C#开发数据库应用系统 理论贯穿案例 北大青鸟参考资料

    在本部分,学习者将学习如何在C#应用程序中集成数据库操作,如使用ADO.NET的DataSet和DataTable对象来处理数据,以及如何通过连接池优化数据库连接。此外,还会介绍事务处理、错误处理等高级话题,确保应用程序的...

    rethinkdb-pool:RethinkDB的连接池

    重新思考数据库池 RethinkDB的连接池安装npm install --save rethinkdb-pool用法建立游泳池var r = require ( 'rethinkdb' )var createPool = require ( 'rethinkdb-pool' )var pool = createPool ( r , { host : '...

    应用javabean制作计算器.doc

    2. **学习数据库连接池的应用**:数据库连接池是一种管理并提供数据库连接的机制,它能够提高应用程序访问数据库的速度和效率。 #### 实验内容 1. **应用JavaBean完成一个计算器的制作**: - 设计一个简单的...

    ORCALe (如 描 述)

    数据库连接以及备份技巧.txt 数据库设计中的14个技巧.txt 数据库主键设计之思考.txt 用连接池提高Servlet访问数据库的效率.txt SQL21自学通.pdf oracle错误代码和信息速查手册.chm oraclewebserver中文手册.chm Java...

    MySQL数据库应用实战教程教学教案.docx

    3. **MySQL的工作原理**:MySQL内部架构包括编程语言交互接口、系统管理和控制工具、连接池、解析器、查询优化器、SQL接口、查询缓存和存储引擎等组件。数据的读写过程涉及到解析SQL语句、查询优化、存储引擎的选择...

    ueberDB:抽象您的数据库,创建数据库。 将每个数据库转换为对象键值存储

    Postgres(单个连接和连接池) 雷迪斯 重新思考 SQLite的 安装 npm install ueberdb2 例子 基本的 const ueberdb = require ( 'ueberdb2' ) ; // mysql const db = new ueberdb . Database ( 'mysql' , { user : ...

    基于SSM的米米商城的设计与实现

    2、使用数据库连接池技术,使用mybatis框架完成底层实体类的创建和数据访问层的实现。 3、实现登录功能。 4、实现登录成功后全部商品分页显示、翻页功能。 5、实现商品增加功能。 6、实现商品删除功能、批量删除...

    JavaEE spring实例工厂的实例方式

    例如,如果你有一个自定义的数据库连接池,你可以创建一个实现`FactoryBean`的类,让Spring通过调用`getObject()`来获取数据库连接池的实例。 2. **基于XML配置的实例工厂**:在Spring的XML配置文件中,可以使用`...

    用设计模式思考 Thinking in Patterns

    这种模式常用于控制资源的共享,比如数据库连接池或者线程池。 2. 工厂模式:提供一个接口来创建对象,但让子类决定实例化哪一个类。工厂模式使代码更易于维护和扩展,因为它解耦了对象的创建和使用。 3. 观察者...

    Java面试宝典

    3. **连接池**:通过连接池管理数据库连接,减少频繁创建和销毁连接带来的开销。 4. **ORM框架**:使用Hibernate、MyBatis等ORM框架简化数据库操作。 #### 六、Java人才技能要求 1. **精通Java**:熟悉Java SE和...

    JDBC 4 ORACLE

    “源码”标签暗示了文章可能深入解析了JDBC驱动或Oracle数据库连接的内部工作原理,甚至可能包括一些示例代码片段。而“工具”标签可能意味着文章涵盖了如何在实际开发环境中集成和使用这些技术,例如IDE插件、构建...

    02.课程设计报告模板.docx

    数据库读写使用DAO模式,结合Druid数据库连接池优化性能;设计了符合第三范式的MySQL数据库表结构。 四、本人负责功能详解 1. 面向对象设计:展示包图和类图,清晰展示类与类之间的关系,以及如何运用面向对象的...

    JSP源码JSP机房上机收费管理系统(源代码+论文+外文翻译)

    - 使用数据库连接池可以显著提高系统的性能。 - 常用的数据库连接池有C3P0、DBCP等。 3. **异常处理机制** - 在Java Web应用中,合理的设计异常处理机制可以提高系统的稳定性和用户体验。 - 例如,可以通过...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part4

     19.1.2 使用配置文件指定的数据库连接池  19.1.3 从容器中获得数据源  19.1.4 由Java应用本身提供数据库连接  19.2 配置事务类型  19.3 把SessionFactory与JNDI绑定  19.4 配置日志  19.5 使用XML格式的配置...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part2

     19.1.2 使用配置文件指定的数据库连接池  19.1.3 从容器中获得数据源  19.1.4 由Java应用本身提供数据库连接  19.2 配置事务类型  19.3 把SessionFactory与JNDI绑定  19.4 配置日志  19.5 使用XML格式的配置...

Global site tag (gtag.js) - Google Analytics