我在Scala中使用Apache pool2
库中的以下代码。池的对象是OlapConnection
(olap4j
类,类似于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)
答案 0 :(得分:1)
如果您打开PooledObjectFactory
的JavaDocs,您可能会看到
返回池时,会在每个实例上调用
passivateObject(org.apache.commons.pool2.PooledObject<T>)
。
- 醇>
destroyObject(org.apache.commons.pool2.PooledObject<T>)
在每个实例被&#34;删除&#34;时被调用来自池(无论是由于validateObject(org.apache.commons.pool2.PooledObject<T>)
的响应,还是由于池实现的特定原因。)无法保证被销毁的实例将被视为主动,被动或大致一致的状态。
换句话说,您应该将资源解除分配逻辑放入 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)
正如人们所期望的那样,给定池配置。