多线程操作的应用程序中,常会用到多个数据库连接。数据库连接创建及连接销毁比较耗费系统资源。在应对频繁的创建和销毁操作时,常需要创建数据库连接池,用以避免频繁的创建及销毁操作。现举例说明连接池(DataBase为封装的数据库操作对象,也可将该对象替换为其他对象,创建链接池)。
头文件如下:
#ifndef CONNECTPOOL_H
#define CONNECTPOOL_H
#include <stdexcept>
#include <exception>
#include <list>
#include "DataBase.h"
using namespace std;
class ConnectPool
{
public:
~ConnectPool();
DataBase* getConnection(); //获取一个数据库连接
void releaseConnection(DataBase* pConn); //释放一个数据库连接
static ConnectPool* getInstace(string url, string connName, string useName, string passWord, int port, int maxSize);
bool isInitConnectPool();
private:
ConnectPool(string url, string connName, string useName, string passWord, int port, int maxSize);
DataBase* createConnection(); //创建数据库连接
void InitConnection(int iInitSize); //初始化连接池
void destoryConnection(DataBase* conn); //销毁一个数据库连接
void destoryConnectPool(); //销毁连接池
private:
int m_curSize; //当前连接数量
int m_maxSize; //最大连接数量
int m_port; //数据库连接端口号
string m_dbName;//数据库名称
string m_useName;//数据库连接用户名
string m_passWord;//数据库连接密码
string m_url; //数据库连接IP
list<string> m_connNameList;//连接名列表
list<DataBase*>m_connList; //连接列表
pthread_mutex_t m_lock; //线程锁
static ConnectPool* m_connPool; //连接池对象
};
#endif // CONNECTPOOL_H
实现文件如下:#include "ConnectPool.h"
ConnectPool* ConnectPool::m_connPool = NULL;
ConnectPool::ConnectPool(string url, string connName, string useName, string passWord, int port, int maxSize)
:m_curSize(0)
,m_maxSize(maxSize)
,m_port(port)
,m_dbName(connName)
,m_useName(useName)
,m_passWord(passWord)
,m_url(url)
,m_connNameList(list<string>())
,m_connList(list<DataBase*>())
,m_lock(NULL)
{
this->InitConnection(m_maxSize/2);
}
ConnectPool::~ConnectPool()
{
this->destoryConnectPool();
}
ConnectPool* ConnectPool::getInstace(string url, string connName, string useName, string passWord, int port, int maxSize)
{
if(m_connPool == NULL)
{
m_connPool = new ConnectPool(url, connName, useName, passWord, port, 20);
}
return m_connPool;
}
void ConnectPool::InitConnection(int iInitSize)
{
for(int k = 0; k < m_maxSize; ++k)
{
char buff[4] = {0};
sprintf_s(buff, 3, "%d", k);
string connName = buff;
m_connNameList.push_back(connName);
}
DataBase* conn = NULL;
pthread_mutex_lock(&m_lock);
for(int i = 0; i < iInitSize; ++i)
{
conn = this->getConnection();
if(conn)
{
m_connList.push_back(conn);
++(this->m_curSize);
}
else
{
perror("创建Connection出错!\n");
}
}
pthread_mutex_unlock(&m_lock);
}
DataBase* ConnectPool::createConnection()
{
DataBase* conn = NULL;
// try
// {
conn = new DataBase();
bool isOk = conn->connectMYSQL(QString::fromStdString(this->m_url),
QString::fromStdString(this->m_dbName),
QString::fromStdString(this->m_useName),
QString::fromStdString(this->m_passWord),
this->m_port, QString::fromStdString(this->m_connNameList.front()));
m_connNameList.pop_front();
if(!isOk)
{
delete conn;
return NULL;
}
return conn;
// }
// catch(sql::SQLExecption& e)
// {
// perror("运行时出错");
// return NULL;
// }
}
DataBase* ConnectPool::getConnection()
{
DataBase* conn = NULL;
pthread_mutex_lock(&m_lock);
if(m_connList.size() > 0)
{
conn = m_connList.front();
m_connList.pop_front();
if(!conn->db.isOpen())
{
delete conn;
conn = this->createConnection();
}
if(conn = NULL)
{
--m_curSize;
}
pthread_mutex_unlock(&m_lock);
return conn;
}
else
{
if(m_curSize < m_maxSize)
{
conn = this->createConnection();
if(conn)
{
++m_curSize;
pthread_mutex_unlock(&m_lock);
return conn;
}
else
{
pthread_mutex_unlock(&m_lock);
return NULL;
}
}
else
{
pthread_mutex_unlock(&m_lock);
return NULL;
}
}
}
void ConnectPool::releaseConnection(DataBase *pConn)
{
if(pConn)
{
pthread_mutex_lock(&m_lock);
m_connList.push_back(pConn);
pthread_mutex_unlock(&m_lock);
}
}
void ConnectPool::destoryConnectPool()
{
pthread_mutex_lock(&m_lock);
list<DataBase*>::iterator iter;
for(iter = m_connList.begin(); iter != m_connList.end(); ++iter)
{
this->destoryConnection(*iter);
}
m_curSize = 0;
m_connList.clear();
delete m_connPool;
pthread_mutex_unlock(&m_lock);
}
void ConnectPool::destoryConnection(DataBase *conn)
{
if(conn)
{
// try
// {
conn->db.close();
// }
// catch(sql::SQLExecption& e)
// {
// perror(e.what());
// }
delete conn;
}
}
bool ConnectPool::isInitConnectPool()
{
if(0 == m_curSize)
{
return false;
}
return true;
}