前言:

网上关于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;
}

程序运行结果:

mysql多进程多线程运行_#include

本连接池初始化时只有2条空闲连接,最大连接数为4 。

偶数线程阻塞形式从连接池获取空闲连接,故一定会获取成功,不过是时间问题,

奇数线程非阻塞形式从连接池获取空闲连接,故可能会出现返回NULL的情况,

前4个先调度的线程占用了空闲连接,导致其余所有的奇数线程全部获取失败,但偶数线程会阻塞等待空闲链接,直到获取到了空闲连接再调用返回。