码迷,mamicode.com
首页 > 其他好文 > 详细

使用commons-pool 构筑简易ConnectionPool

时间:2015-07-14 20:09:00      阅读:138      评论:0      收藏:0      [点我收藏+]

标签:

 

  在编程中,池的运用应当是很广泛了,如连接池,线程池,资源池等。实际编程中,我们也可以构建Cache池,也可能有涉及到其它的情况,需要使用pool方案来解决。为此Apache中开发了一个通用的Pool工具:commons-pool,现在这个工具有两个版本(1.X, 2.X)并且有很大的不同。这里说的是Commons-pool 的1.X版本。

 

本文将分为两个部分,第一部分介绍commons-pool 1.X API。第二部分使用commons-pool构筑简易ConnectionPool。

 

第一部分Commons-pool 1.X 介绍

 

下面是commons-pool的设计方案:

 技术分享

 

 

总体来看,就是由ObjectPoolFactory创建出ObjectPool,然后在使用ObjectPool的过程中(例如borrowObject(),returnObject()等方法),通过ObjectFactory,来对特定的对象进行处理。

        由于官方文档中,对于commons-pool的描述并不多,所以只能看代码来了解了。

如果你的ObjectPool组件都设计完毕,在使用ObjectPool时,入口就是ObjectPool。

下面就看看ObjectPool的说明 :

 技术分享

 

从这个说明上可以知道,只需要在合适的地方合理的调用borrowObject()、invalidateObject()、returnObject() 对对象进行处理即可。通过源码知道,这几个方法在处理过程中会委托给PoolableObjectFactory来处理,下面就来看看这个接口的设计。

 技术分享 

 

从上面的描述也可以看出:

1、borrowObject时,会先从pool中找出一个idle的对象,如果找不到,就可以使用makeObject()来创建对象,并使用activateObject()将对象设置为active状态。如果找到了对象,不需要调用makeObject(),但是会调用validateObject()。

2、如果一个对象要被抛弃,就可以使用invaliateObejct()将对象设置为无效状态。

3、如果对象正常使用完毕,就应该让对象返回pool中,并将其钝化,也就是设置为idle状态。

 

通过对commons-pool的了解,应该就可以明白,在使用commons-pool,可以对ObjectPoolFactory、PoolableObjectFactory进行定制,在必要的情况下,也可以对ObjectPool进行定制。

 

 

第二部分使用commons-pool构筑简易ConnectionPool

// 定义一个ConnectionPoolFactory,目前中是实现了构建器,其它功能还待完善。

package com.fjn.frame.apache.commons.pool.connectionPool;

import org.apache.commons.pool.PoolableObjectFactory;
import org.apache.commons.pool.impl.GenericObjectPoolFactory;

public class ConnectionPoolFactory extends GenericObjectPoolFactory{

    public ConnectionPoolFactory(PoolableObjectFactory factory, int maxActive,
            byte whenExhaustedAction, long maxWait, int maxIdle, int minIdle,
            boolean testOnBorrow, boolean testOnReturn,
            long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun,
            long minEvictableIdleTimeMillis, boolean testWhileIdle,
            long softMinEvictableIdleTimeMillis, boolean lifo) {
        super(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, minIdle,
                testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis,
                numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle,
                softMinEvictableIdleTimeMillis, lifo);
    }
    
}

 

package com.fjn.frame.apache.commons.pool.connectionPool;

public class ConnectionInfo {
    ConnectionFactory factory;

    public ConnectionFactory getFactory() {
        return factory;
    }

    public void setFactory(ConnectionFactory factory) {
        this.factory = factory;
    }
}

// 连接工厂

package com.fjn.frame.apache.commons.pool.connectionPool;

import java.sql.DriverManager;

import org.apache.commons.pool.BasePoolableObjectFactory;

public class ConnectionFactory extends BasePoolableObjectFactory{
    private String driverClass;
    private String username;
    private String password;
    private String url;

    
    
    public String getDriverClass() {
        return driverClass;
    }

    public void setDriverClass(String driverClass) {
        this.driverClass = driverClass;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    Connection _createConnection() throws Exception{
        Connection connection=null;
        java.sql.Connection conn=null;
        Class.forName(driverClass);
        conn= DriverManager.getConnection(url, username, password);
        connection=new Connection();
        connection.setConn(conn);
        ConnectionInfo connInfo=new ConnectionInfo();
        connInfo.setFactory(this);
        return connection;
    }
    
    // 只为了测试使用
    private Object createConnection(){
        return new Connection();
    }
    
    @Override
    public Object makeObject() throws Exception {
        return createConnection();
    }

}

// Connection

package com.fjn.frame.apache.commons.pool.connectionPool;

import java.sql.SQLException;

public class Connection {
    private java.sql.Connection conn;
    private ConnectionInfo connInfo;
    public java.sql.Connection getConn() {
        return conn;
    }
    public void setConn(java.sql.Connection conn) {
        this.conn = conn;
    }
    public ConnectionInfo getConnInfo() {
        return connInfo;
    }
    public void setConnInfo(ConnectionInfo connInfo) {
        this.connInfo = connInfo;
    }
    
    public void close(){
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

 

// 测试

package com.fjn.frame.apache.commons.pool.connectionPool;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.impl.GenericObjectPool;

public class ConnectionManager {
    private ObjectPool pool;
    private ConnectionFactory connFactory;
    private ConnectionPoolFactory connPoolFactory;

    public void initConnectionPool(int maxNum, int maxIdleCount,
            int minIdleCount, long maxWaitTime) {
        int maxActive = maxNum;
        byte whenExhaustedAction = GenericObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION;
        long maxWait = maxWaitTime;
        int maxIdle = maxIdleCount;
        int minIdle = minIdleCount;
        boolean testOnBorrow = GenericObjectPool.DEFAULT_TEST_ON_BORROW;
        boolean testOnReturn = GenericObjectPool.DEFAULT_TEST_ON_RETURN;
        long timeBetweenEvictionRunsMillis = GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
        int numTestsPerEvictionRun = GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
        long minEvictableIdleTimeMillis = GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
        boolean testWhileIdle = GenericObjectPool.DEFAULT_TEST_WHILE_IDLE;
        long softMinEvictableIdleTimeMillis = GenericObjectPool.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
        boolean lifo = GenericObjectPool.DEFAULT_LIFO;
        connPoolFactory = new ConnectionPoolFactory(connFactory, maxActive,
                whenExhaustedAction, maxWait, maxIdle, minIdle, testOnBorrow,
                testOnReturn, timeBetweenEvictionRunsMillis,
                numTestsPerEvictionRun, minEvictableIdleTimeMillis,
                testWhileIdle, softMinEvictableIdleTimeMillis, lifo);
        
    }

    public static void main(String[] args) {
        final ConnectionManager mgr = new ConnectionManager();
        mgr.connFactory = new ConnectionFactory();
        mgr.connFactory.setDriverClass("com.mysql.jdbc.Driver");
        mgr.connFactory.setPassword("mysql");
        mgr.connFactory.setUsername("mysql");
        mgr.connFactory.setUrl("url:localhost:3306"); // 改成真实的URL

        mgr.initConnectionPool(1000, 50, 5, 1000 * 60);
        mgr.pool = mgr.connPoolFactory.createPool();

        final AtomicInteger count = new AtomicInteger(0);
        
        int threadNum = Runtime.getRuntime().availableProcessors();
        ExecutorService client = Executors.newFixedThreadPool(threadNum);
        for (int i = 0; i < threadNum; i++) {
            client.submit(new Runnable() {
                @Override
                public void run() {
                    while (true && count.get() < 100) {
                        try {
                            Thread.sleep(500);
                        } catch (InterruptedException e1) {
                            e1.printStackTrace();
                        }
                        Connection connection = null;

                        try {
                            connection = (Connection) mgr.pool.borrowObject();
                            try {

                                int value = count.incrementAndGet();
                                if (value < 100) {
                                    String threadName = Thread.currentThread()
                                            .getName();

                                    int activeNum = mgr.pool.getNumActive();
                                    int idleNum = mgr.pool.getNumIdle();
                                    String content = "ThreadName: "
                                            + threadName
                                            + "\t SQL: "
                                            + "insert into tableA ( ct ) values (‘"
                                            + value + "‘); \t activeNum="
                                            + activeNum + "\t idleNum="
                                            + idleNum;
                                    System.out.println(content);
                                }

                            } catch (Exception e) {
                                mgr.pool.invalidateObject(connection);
                                connection = null;
                            } finally {
                                // make sure the object is returned to the pool
                                if (null != connection) {
                                    mgr.pool.returnObject(connection);
                                }
                            }
                        } catch (Exception e) {
                            // failed to borrow an object
                        }

                    }
                }
            });
        }
    }


}

 

目前使用这个小程序,应用可以跑起来了,但是它并不是一个真实的连接池实现,需要的工作还有很多。

这个小程序,只是一个commons-pool 1.X的demo ,也只是为了证明我上面的想法,具体如何使用,还需要深入的研究。

 

使用commons-pool 构筑简易ConnectionPool

标签:

原文地址:http://www.cnblogs.com/f1194361820/p/4646131.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!