前言:
网上关于Linux C/C++的连接池相关项目很少,即便是有也难以满足我的需求,比如:
1、无法支持阻塞形式(线程休眠等待空闲连接)获取空闲连接;
2、网上流传的基于mysql++开发的连接池,还需要引入boost等三方库,稍显繁琐;
基于以上原因,本人自己写了这个连接池,有问题下方留言,大家共同进步!
连接池的逻辑:
初始化连接池时创建一定数量的空闲连接,当有线程主动从连接池获取连接时,若没有空闲连接且当前连接池总连接数小于最大连接数,则连接池会创建新的连接并返回,若连接总数已达上限则本连接池提供阻塞等待空闲连接和直接返回NULL两种形式的接口
本连接池的特点:
1、支持多线程;
2、从连接池获取空闲连接时支持阻塞(直到获取到空闲连接)和非阻塞(没有空闲连接直接返回,获取互斥锁的时间可以忽略不计)两种形式;
3、托管了mysql的连接;
本项目存在的缺点以及下一步计划:
1、没有将mysql提供的API封装,故在获取到空闲连接后还需要调用相关API进行相关CURD操作;
2、对于长时间空闲的连接,未予以自动释放;
总结:
虽然本连接池还有存在一些问题(前面提到的问题),但足以满足普通项目的开发了,有问题可以在下方留言!
源码地址:
https://github.com/1002130915/CConnectPool
CConnectPool接口说明:
/**
* @brief 创建连接池 \n
* 在主线程中创建连接池,创建后需要调用FreePool予以释放
* 创建失败程序会打印错误信息并终止运行
*/
static void CreatePool();
/**
* @brief 释放连接池 \n
* 需要在主线程中调用该接口
*/
static void FreePool();
/**
* @brief 获取连接 \n
* 支持多线程,使用完成后需调用PutConnect,归还连接,本函数为阻塞函数,直到有可用连接才调用返回
* @return 返回数据库连接
* --NULL表示调用失败
*/
static MYSQL* GetConnect();
/**
* @brief 获取连接 \n
* 支持多线程,使用完成后需调用PutConnect,归还连接,本函数调用后立刻返回,若没有空闲连接则返回NULL
* @return 返回数据库连接
* --NULL表示调用失败
* */
static MYSQL* TryGetConnect();
/**
* @brief 向连接池归还连接 \n
* 支持多线程
* @param[in] pConn 需要归还的数据库连接
* */
static void PutConnect(MYSQL*pConn);
测试代码:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include "mysql/mysql.h"
#include "CConnectPool.h"
void* threadFunc1(void* pNum)
{
//调用阻塞函数从连接池取一个连接,占用15秒钟后释放
MYSQL *pConn = CConnectPool::GetConnect();
if(pConn)
{
printf("get connect ok! id: %d\n",*(int*)pNum);
}
else
{
printf("get connect error!id: %d\n",*(int*)pNum);
}
sleep(10);
if(NULL != pConn)
{
CConnectPool::PutConnect(pConn);
}
delete pNum;
}
void* threadFunc2(void* pNum)
{
//非阻塞从连接池取一个连接,占用15秒钟后释放
MYSQL *pConn = CConnectPool::TryGetConnect();
if(pConn)
{
printf("get connect ok!id: %d\n",*(int*)pNum);
}
else
{
printf("get connect error!id: %d\n",*(int*)pNum);
}
sleep(10);
if(NULL != pConn)
{
CConnectPool::PutConnect(pConn);
}
delete pNum;
}
int main()
{
//主线程中调用初始化连接池函数
CConnectPool::CreatePool();
pthread_t threads[15];
//编号
int *pNum = NULL;
//偶数线程调用阻塞函数从连接池获取空闲连接
//奇数线程调用非阻塞函数从连接池获取空闲连接
for(int i=0;i<15;++i)
{
pNum = new int;
*pNum = i;
if(i%2 == 0)
{
pthread_create(&threads[i],NULL,threadFunc1,pNum);
}
else
{
pthread_create(&threads[i],NULL,threadFunc2,pNum);
}
}
for(int i=0;i<15;++i)
{
pthread_join(threads[i],NULL);
}
//主线程中释放连接池
CConnectPool::FreePool();
printf("over \n");
return 0;
}
程序运行结果:
本连接池初始化时只有2条空闲连接,最大连接数为4 。
偶数线程以阻塞形式从连接池获取空闲连接,故一定会获取成功,不过是时间问题,
奇数线程以非阻塞形式从连接池获取空闲连接,故可能会出现返回NULL的情况,
前4个先调度的线程占用了空闲连接,导致其余所有的奇数线程全部获取失败,但偶数线程会阻塞等待空闲链接,直到获取到了空闲连接再调用返回。