跳至主要內容

连接池单例模式实践

张威大约 4 分钟mysqlmysql连接池

连接池单例模式实践

//饿汉式 线程安全的单例
class ConnectionPool {
public:
    static ConnectionPool* getConnectionPool();
private:
    ConnectionPool();
    ~ConnectionPool();
};


// 线程安全的懒汉单例函数接口
ConnectionPool* ConnectionPool::getConnectionPool() { //静态函数的实现,不写static
    static ConnectionPool pool; //静态局部变量的初始化,编译器会生成lock和unlock
    return &pool;
}
#ifndef _CONNECTIONPOOL_H
#define _CONNECTIONPOOL_H

#include <string>
#include <queue>
#include <mutex>
#include "connection.h"

using std::string;
using std::queue;
using std::mutex;

class ConnectionPool {
public:
    static ConnectionPool* getConnectionPool();
private:
    ConnectionPool();
    ~ConnectionPool();
public: //测试的时候可以先变成共有的
    bool loadConfigFile();

private:
	string _ip; // mysql的ip地址
	unsigned short _port; // mysql的端口号 3306
	string _username; // mysql登录用户名
	string _password; // mysql登录密码
	string _dbname; // 连接的数据库名称
	int _initSize; // 连接池的初始连接量
	int _maxSize; // 连接池的最大连接量
	int _maxIdleTime; // 连接池最大空闲时间
	int _connectionTimeout; // 连接池获取连接的超时时间
    
    queue<Connection*> _connectionQue;  // 存储mysql连接的队列
    mutex _queueMutex;  // 维护连接队列的线程安全互斥锁
};

#endif //_CONNECTIONPOOL_H
#include "connectionPool.h"
#include <iostream>
#include "public.h"

using std::cout;
using std::endl;

ConnectionPool::ConnectionPool() {}
ConnectionPool::~ConnectionPool() {}

// 线程安全的懒汉单例函数接口
ConnectionPool* ConnectionPool::getConnectionPool() { //静态函数的实现,不写static
    static ConnectionPool pool; //静态局部变量的初始化,编译器会生成lock和unlock
    return &pool;
}

bool ConnectionPool::loadConfigFile() {
    FILE* pf = fopen("mysql.cnf","r");
    if(pf == nullptr) {
        LOG("mysql.cnf file is not exit!");
        return false;
    }

    while(!feof(pf)) {  //文件不为空
        char line[1024] = {0};
        fgets(line, sizeof(line), pf);
        string str = line;
        int idx = str.find('=', 0); //从第0位开始找'='的下标
        if(idx == -1) {  //无效的配置项
            continue;
        }

        // password=123456\n
        int endidx = str.find('\n', idx); //从第idx位开始找'\n'的下标

        string key = str.substr(0,idx); //从第0位开始idx个字符
        string value = str.substr(idx + 1, endidx - (idx + 1));

        cout << key << '=' << value << endl;
        
    }
    
    return true;
}

feof()原理和用法-CSDN博客open in new window

feof()如果文件结束,则返回非0值,否则返回0

[fgets()函数的详解-使用技巧-C语言基础_fgets函数用法-CSDN博客](https://blog.csdn.net/Devour_/article/details/110955333#:~:text=一般用法: char a %3D {0}%3B fgets,(a%2C 100%2C stdin)%3B 通俗来讲的话,fgets()函数的作用就是用来读取一行数据的。 但要详细且专业的说的话,fgets()函数的作用可以这么解释:从第三个参数指定的流中读取最多第二个参数大小的字符到第一个参数指定的容器地址中。 在这个过程中,在还没读取够第二个参数指定大小的字符前,读取到换行符'n'或者需要读取的流中已经没有数据了。)

char *fgets(char *restrict str, int size, FILE *restrict stream)

fgets()函数的作用就是用来读取一行数据的,读取出错或读取文件时文件为空,则返回一个空指针

fgets()函数的最大读取大小是其“第二个参数减1”,

  • 这是由于字符串是以’\0’为结束符的,fgets()为了保证输入内容的字符串格式,当输入的数据大小超过了第二个参数指定的大小的时候,fgets()会仅仅读取前面的“第二个参数减1”个字符,而预留1个字符的空间来存储字符串结束符’\0’

C++String中的find用法_c++ string find-CSDN博客open in new window

C++string类中substr()函数的使用方法_c++ string substr-CSDN博客open in new window

string x=s.substr() //默认时的长度为从开始位置到尾 string y=s.substr(5) //获得字符串s中 从第5位开始到尾的字符串 string z=s.substr(5,3); //获得字符串s中 从第5位开始的长度为3的字符串

#include <iostream>
#include "connection.h"
#include "connectionPool.h"
#include "public.h"

using std::cout;
using std::endl;

int main() {
    // Connection conn;
    // char sql[1024] = {0};
    // sprintf(sql, "insert into user(name, age, sex) values('%s', %d, '%s')",
    //  "guan yu", 33, "male");

    // bool ret = conn.connection("127.0.0.1", 3306, "root", "147258", "school");
    // if(!ret) {
    //     LOG("连接失败");
    // }
    // conn.update(sql);

    ConnectionPool::getConnectionPool()->loadConfigFile();

}
#数据库连接池的配置文件,下面和宏一样就不要加多余的空格了
ip=127.0.0.1
port=3306
username=root
password=147258
initSize=10
maxSize=1024
// 连接池最大空闲时间默认单位是秒
maxIdleTime=60
// 连接池获取连接的超时时间单位是毫秒
connectionTimeOut=100
image-20240408210426812
image-20240408210426812