使用commons.pool2实现mysql连接池

Posted 数客联盟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用commons.pool2实现mysql连接池相关的知识,希望对你有一定的参考价值。

在使用mysql进行开发的时候,经常会遇到如何控制mysql连接数的问题。比较好的解决方案就是使用一个连接池,控制连接数。org.apache.commons.pool2中提供了对象池管理的框架,可以很方便的解决这个问题。

具体实现

 1import java.sql.{Connection, DriverManager}
2import org.apache.commons.pool2.impl.{DefaultPooledObject, GenericObjectPool}
3import org.apache.commons.pool2.{BasePooledObjectFactory, PooledObject}
4object MysqlConnectionPool {
5  def apply(url: String, userName: String, password: String, className: String): GenericObjectPool[Connection] = {
6    new GenericObjectPool[Connection](new MysqlConnectionFactory(url, userName, password, className))
7  }
8}
9class MysqlConnectionFactory(url: String, userName: String, password: String, className: String) extends BasePooledObjectFactory[Connection]{
10  override def create(): Connection = {
11    Class.forName(className)
12    DriverManager.getConnection(url, userName, password)
13  }
14  override def wrap(conn: Connection): PooledObject[Connection] = new DefaultPooledObject[Connection](conn)
15  override def validateObject(pObj: PooledObject[Connection]) = !pObj.getObject.isClosed
16  override def destroyObject(pObj: PooledObject[Connection]) = pObj.getObject.close()
17}

测试

 1import java.sql.{Connection, ResultSet, Statement}
2import org.apache.commons.pool2.impl.{GenericObjectPool, GenericObjectPoolConfig}
3object RunApp {
4  def getData(pool: GenericObjectPool[Connection]): Unit ={
5    var stmt: Statement = null
6    var rs: ResultSet = null
7    try {
8      val conn = pool.borrowObject()
9      stmt = conn.createStatement
10      rs = stmt.executeQuery("SELECT * FROM user")
11      for (index <- 1 to rs.getMetaData.getColumnCount){
12        println(rs.getMetaData.getColumnName(index))
13      }
14      Thread.sleep(10000)
15      pool.returnObject(conn)
16    } catch {
17      case ex: Exception =>
18        // handle any errors
19        System.out.println("SQLException: " + ex.getMessage)
20    }
21  }
22  def main(args: Array[String]): Unit = {
23    val conf = new GenericObjectPoolConfig
24    conf.setMaxTotal(2)
25    conf.setMaxIdle(1)
26    conf.setMaxWaitMillis(20000)
27    val pool = MysqlConnectionPool("jdbc:mysql://localhost:3306/tutorials", "root", "root", "com.mysql.jdbc.Driver")
28    pool.setConfig(conf)
29    for (_ <- 1 to 3){
30      new Thread(new Runnable {
31        override def run(): Unit = {
32          getData(pool)
33        }
34      }).start()
35    }
36  }
37}

测试代码中通过conf.setMaxTotal(2)设置最大使用的连接数为2,也就是说只能同时有两个对象连接mysql,其他对象等待,并且等待的超时时间为conf.setMaxWaitMillis(20000)。那么在main函数中启动了3个线程同时对数据库进行查询操作,并且每次查询都会sleeep 10秒。程序运行的时候可以通过show full processlist;查看mysql的连接数,会发现只有2个对象会同时连接mysql,只有等其中一个运行结束后pool.returnObject(conn)将连接返还给连接池,第三个线程才会得到资源连接mysql。
conf.setMaxIdle(1)的作用是最多处于idle状态的对象的个数,如果超过这个数量,会自动调用MysqlConnectionFactory中的destroyObject方法销毁对象。

总结

通过本文介绍的方式可以有效的控制mysql的连接数。


以上是关于使用commons.pool2实现mysql连接池的主要内容,如果未能解决你的问题,请参考以下文章

解决dbcp数据库连接池错误

通过线程池,从hbase中拿数据

基于Apache组件,分析对象池原理

Caused by: java.lang.NoClassDefFoundError: org/apache/commons/pool2/impl/GenericObjectPoolConfig(示例代

[redis] The type org.apache.commons.pool2.impl.GenericObjectPoolConfig cannot be resolved.It is indi

Spring Boot集成Redis启动失败Caused by: java.lang.ClassNotFoundException: org.apache.commons.pool2.impl.G