mahone-tech

Java对象池与连接池

原文链接:

对象池工厂:利用对象池中封闭的创建、获取、归还和销毁操作对象。

  • 当需要拿一个池对象的时候, 就从容器中取出一个。
  • 如果容器中没有的话, 而且又没有达到容器的最大限制, 那么就调用池对象工厂, 新建一个池对象, 并调用工厂的激活方法, 对创建的对象进行激活, 验证等一系列操作;
  • 如果已经达到池容器的最大值, 而对象池中又经没有空闲的对象, 那么将会继续等待, 直到有新的空闲的对象被丢进来, 当然这个等待也是有限度的, 如果超出了这个限度, 对象池就会抛出异常. 

当将用完的池对象归还到对象池中的时候, 对象池会调用池对象工厂对该池对象进行验证:

  • 如果验证不通过则被认为是有问题的对象, 将会被销毁;
  • 如果容器已经满了, 这个归还池对象将变的"无家可归", 也会被销毁,;
  • 如果不属于上面两种情况, 对象池就会调用工厂对象将其钝化并放入容器中.

在整个过程中, 激活, 检查, 钝化处理都不是必须的, 因此我们在实现PoolableObjectFactory接口的时候, 一般不作处理, 给空实现即可, 所以诞生了BasePoolableObjectFactory. 

对象池共分5种、2类:

  • GenericObjectPool :CursorableLinkedList容器
  • GenericKeyedObjectPool :CursorableLinkedList容器
  • SoftReferenceObjectPool :ArrayList容器--一次性创建所有池化对象, 并对容器中的对象进行了软引用(SoftReference)处理, 从而保证在内存充足的时候池对象不会轻易被jvm垃圾回收, 从而具有很强的缓存能力.
  • StackObjectPool : Stack容器
  • StackKeyedObjectPoo : Stack容器

四种池对象的区别主要体现在内部的容器的区别:

Stack遵循"后进先出"的原则并能保证线程安全;

CursorableLinkedList是一个内部用游标(cursor)来定位当前元素的双向链表, 是非线程安全的, 但是能满足对容器的并发修改.ArrayList是非线程安全的, 便利方便的容器.

一、不带Key的对象池

   

二、带Key的对象池

  普通的对象池通过makeObject()方法创建的对象基本上都是一模一样的, 因为没法传递参数来对池对象进行定制

 

  

使用对象池步骤:

创建一个池对象工厂

  • 将工厂注入到对象池中
  • 取池对象时:borrowOjbect
  • 归还池对象:returnObject
  • 销毁池对象:  clear()
  • 连池对象工厂一起销毁:close()

borrowOjbect:  

  

 returnObject:

   

invalidateObject: 

   

 

源代码:

/**
 * 创建连接
 *  
 */
public class ConnectionUtils {
	// 一些common-dbcp内部定义的protocol
	private static final String POOL_DRIVER_KEY = "jdbc:apache:commons:dbcp:";
	private static final String POLLING_DRIVER = "org.apache.commons.dbcp.PoolingDriver";


	/**
	 * 取得池化驱动器
	 * 
	 * @return
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 */
	private static PoolingDriver getPoolDriver() throws ClassNotFoundException,
			SQLException {
		Class.forName(POLLING_DRIVER);
		return (PoolingDriver) DriverManager.getDriver(POOL_DRIVER_KEY);
	}


	/**
	 * 销毁所有连接
	 * 
	 * @throws Exception
	 */
	public static void destory() throws Exception {
		PoolingDriver driver = getPoolDriver();
		String[] names = driver.getPoolNames();
		for (String name : names) {
			driver.getConnectionPool(name).close();
		}
	}


	/**
	 * 从连接池中获取数据库连接
	 */
	public static Connection getConnection(TableMetaData table)
			throws Exception {
		String key = table.getConnectionKey();


		PoolingDriver driver = getPoolDriver();


		ObjectPool pool = null;
		// 这里找不到连接池会抛异常, 需要catch一下
		try {
			pool = driver.getConnectionPool(key);
		} catch (Exception e) {
		}
		
		if (pool == null) {
			// 根据数据库类型构建连接工厂
			ConnectionFactory connectionFactory = null;
			if (table.getDbAddr() != null
					&& TableMetaData.DB_TYPE_MYSQL == table.getDbType()) {
				Class.forName(TableMetaData.MYSQL_DRIVER);
				connectionFactory = new DriverManagerConnectionFactory(table
						.getDBUrl(), null);
			} else {
				Class.forName(TableMetaData.ORACLE_DRIVER);
				connectionFactory = new DriverManagerConnectionFactory(table
						.getDBUrl(), table.getDbuser(), table.getDbpass());
			}
			
			// 构造连接池
			ObjectPool connectionPool = new GenericObjectPool(null);
			new PoolableConnectionFactory(connectionFactory, connectionPool,
					null, null, false, true);
			
			// 将连接池注册到driver中
			driver.registerPool(key, connectionPool);
		}


		// 从连接池中拿一个连接
		return DriverManager.getConnection(POOL_DRIVER_KEY + key);
	}
}

  

 

发表于 2017-01-04 13:37  MahoneTech  阅读(407)  评论(0编辑  收藏  举报
 

分类:

技术点:

相关文章: