Apache Pool 2库 - 连接未自动关闭

时间:2018-04-24 01:52:20

标签: scala olap4j apache-commons-pool

我在Scala中使用Apache pool2库中的以下代码。池的对象是OlapConnectionolap4j类,类似于SQL连接)。

问题是,当池化对象的数量超过最大值时,我无法使池自动关闭

如果我将对象返回到池(使用pool.returnObject),则会触发passivateObject。如果我在passivateObject中关闭连接,我会在每次返回一个对象时将其关闭,而这不是我想要的 - 我需要缓存打开的连接。如果我关闭passivateObject中的连接,则永远不会关闭。

如何使这项工作?

Scala代码:

class OlapConnectionUtil (val pool: ObjectPool[OlapConnection]) {
     def connect = {
        pool.borrowObject
     }
     def close(olapConnection: OlapConnection) = {
       pool.returnObject(olapConnection)
     }
}

class OlapConnectionFactory extends BasePooledObjectFactory[OlapConnection] {

  override def create = {           
      val connectionString = "jdbc:mondrian:Jdbc=jdbc:mysql://localhost:3306/foodmart?" + 
            "user=x&password=x;Catalog=FoodMart.xml;JdbcDrivers=com.mysql.jdbc.Driver"           
       val connection = DriverManager.getConnection(connectionString)
       connection.unwrap(classOf[OlapConnection])
    }

    override def wrap(olapConnection: OlapConnection) = 
                                  new DefaultPooledObject(olapConnection)

    override def passivateObject(pooledObject: PooledObject[OlapConnection] ) {
      println("passivateObject WAS CALLED")
      pooledObject.getObject.close
    }    

  }


class Test  {

  val olapConnectionFactory = new OlapConnectionFactory

  def test = { 

     val config = new GenericObjectPoolConfig
     config.setMaxIdle(5)
     config.setMaxTotal(10)

     val util = new OlapConnectionUtil(
                 new GenericObjectPool[OlapConnection](olapConnectionFactory,config))
     val olapConnection = util.connect

     // do stuff with olapConnection

     util.close(olapConnection)

1 个答案:

答案 0 :(得分:1)

如果您打开PooledObjectFactory的JavaDocs,您可能会看到

  
      返回池时,会在每个实例上调用
  1. passivateObject(org.apache.commons.pool2.PooledObject<T>)。   
  2.   
  3. destroyObject(org.apache.commons.pool2.PooledObject<T>)在每个实例被&#34;删除&#34;时被调用来自池(无论是由于validateObject(org.apache.commons.pool2.PooledObject<T>)的响应,还是由于池实现的特定原因。)无法保证被销毁的实例将被视为主动,被动或大致一致的状态。
  4.   

换句话说,您应该将资源解除分配逻辑放入 destroyObject 。以下是使用虚假OlapConnection实施

对您进行的修改测试
import org.apache.commons.pool2._
import org.apache.commons.pool2.impl._

// fake!
case class OlapConnection(val id: Int) {


  def close(): Unit = {
    println(s"Close was called for $this")
  }
}

class OlapConnectionUtil(val pool: ObjectPool[OlapConnection]) {
  def connect = {
    pool.borrowObject
  }

  def close(olapConnection: OlapConnection) = {
    pool.returnObject(olapConnection)
  }
}

class OlapConnectionFactory extends BasePooledObjectFactory[OlapConnection] {
  var cnt = 0

  override def create = {
    cnt += 1
    new OlapConnection(cnt)
  }

  override def wrap(olapConnection: OlapConnection) =
    new DefaultPooledObject(olapConnection)

  override def passivateObject(pooledObject: PooledObject[OlapConnection]) {
    println("-passivateObject was called")
  }

  override def destroyObject(pooledObject: PooledObject[OlapConnection]): Unit = {
    super.destroyObject(pooledObject)
    println("--destroyObject was called")
    pooledObject.getObject.close
  }
}

object Test {

  val olapConnectionFactory = new OlapConnectionFactory

  def test = {

    val config = new GenericObjectPoolConfig
    config.setMaxIdle(5)
    config.setMaxTotal(10)

    val util = new OlapConnectionUtil(new GenericObjectPool[OlapConnection](olapConnectionFactory, config))
    val initConnections = (1 to 10).map(i => util.connect).toList
    val closeCons = initConnections
    Thread.sleep(100)
    println("Start closing")
    closeCons.zipWithIndex.foreach(ci => {
      Thread.sleep(100)
      println(s"Before close ${ci._2 + 1}")
      util.close(ci._1)
      println(s"After close ${ci._2 + 1}")
    })
  }
}

此代码生成的输出是:

  

关闭前1   
-passivateObject被调用   
关闭1   
关闭前2   
-passivateObject被调用   
关闭2   
关闭前3   
-passivateObject被调用   
关闭3   
关闭前4   
-passivateObject被调用   
关闭4   
关闭前5   
-passivateObject被调用   
关闭5   
关闭前6   
-passivateObject被调用   
- 调用了--destroyObject   
关闭被要求OlapConnection(6)   
关闭6   
关闭前7   
-passivateObject被调用   
- 调用了--destroyObject   
关闭被称为OlapConnection(7)   
关闭7   
关闭前8   
-passivateObject被调用   
- 调用了--destroyObject   
关闭被要求OlapConnection(8)   
关闭8   
关闭前9   
-passivateObject被调用   
- 调用了--destroyObject   
关闭被称为OlapConnection(9)   
关闭9   
关闭前10   
-passivateObject被调用   
- 调用了--destroyObject   
关闭被称为OlapConnection(10)   
关闭10后

正如您在此输出中所看到的那样close正在调用,因为OlapConnection(6)正如人们所期望的那样,给定池配置。