From 9855ff4f915c8959ca27c2e95faeb3cf6a288580 Mon Sep 17 00:00:00 2001 From: lzz <xiguabobo_2020@qq.com> Date: 星期六, 09 十一月 2024 16:07:13 +0800 Subject: [PATCH] 添加 --- Server/王琨元/code/ConnectionPool.cpp | 216 +++++++++++++++++++++++------------------------------ 1 files changed, 93 insertions(+), 123 deletions(-) diff --git "a/Server/\347\216\213\347\220\250\345\205\203/code/ConnectionPool.cpp" "b/Server/\347\216\213\347\220\250\345\205\203/code/ConnectionPool.cpp" index 367a7f1..2fff64c 100644 --- "a/Server/\347\216\213\347\220\250\345\205\203/code/ConnectionPool.cpp" +++ "b/Server/\347\216\213\347\220\250\345\205\203/code/ConnectionPool.cpp" @@ -1,131 +1,101 @@ +#include "stdafx.h" #include "ConnectionPool.h" -ConnectionPool::ConnectionPool() -{ - if (!parseXmlFile()) - return; - for (m_num = 0; m_num < m_minSize;) { - bool flag = addConnection(); - if (!flag) { - return; - } - } - // 如果子线程的任务函数是类的非静态函数,我们需要指定任务函数的地址和任务函数的所有者 - thread producer(&ConnectionPool::productConnection, this); // 创建连接 - thread recycler(&ConnectionPool::recycleConnection, this); // 检测并销毁连接 - // 线程分离,防止阻塞主线程 - producer.detach(); - recycler.detach(); + + +ConnectionPool::ConnectionPool() { + + + m_min_conn = 5; // 假设最小连接数为 5 + m_max_conn = 10; // 假设最大连接数为 10 + m_timeout = 1000; // 假设连接超时时间为 1000 毫秒 + max_del_time = 60000; // 假设最大空闲时间为 60000 毫秒 + + for (int i = 0; i < m_min_conn; i++) { + addConnection(); + } + // 创建一个线程,对连接数进行监控 ,连接数不足就再继续创建 + thread producer(&ConnectionPool::produce, this); + // 对连接数进行监控 ,如果有太多空闲得线程 ,那么就对其进行销毁 + thread recycler(&ConnectionPool::recycle, this); + + // 线程分离 + producer.detach(); + recycler.detach(); } -ConnectionPool::~ConnectionPool() -{ - while (!m_connections.empty()) { - MysqlConn* conn = m_connections.front(); - m_connections.pop(); - delete conn; - } + + +ConnectionPool::~ConnectionPool() { + while (!m_connkQueue.empty()) { + MysqlConn* conn = m_connkQueue.front(); + m_connkQueue.pop(); + delete conn; + } } -bool ConnectionPool::parseXmlFile() -{ - TiXmlDocument xml("mysql.xml"); - // 加载文件 - bool res = xml.LoadFile(); - if (!res) { - return false; // 提示 - } - // 根 - TiXmlElement* rootElement = xml.RootElement(); - TiXmlElement* childElement = rootElement->FirstChildElement("mysql"); - // 读取信息 - m_ip = childElement->FirstChildElement("ip")->GetText(); - m_port = static_cast<unsigned short>(stoi(string(childElement->FirstChildElement("port")->GetText()))); - m_user = childElement->FirstChildElement("username")->GetText(); - m_passwd = childElement->FirstChildElement("password")->GetText(); - m_dbName = childElement->FirstChildElement("dbName")->GetText(); - m_minSize = static_cast<int>(stoi(string(childElement->FirstChildElement("minSize")->GetText()))); - m_maxSize = static_cast<int>(stoi(string(childElement->FirstChildElement("maxSize")->GetText()))); - m_maxIdleTime = static_cast<int>(stoi(string(childElement->FirstChildElement("maxIdleTime")->GetText()))); - m_timeout = static_cast<int>(stoi(string(childElement->FirstChildElement("timeout")->GetText()))); - return true; + +void ConnectionPool::addConnection() { + MysqlConn* conn = new MysqlConn(); + if (!conn->isConnected()) { + cout << "ConnectionPool connect to mysql is failed!" << endl; + delete conn; + return; + } + conn->refreshActiveTime(); + m_connkQueue.push(conn); + m_cond.notify_one(); // 唤醒一个线程 } -bool ConnectionPool::addConnection() -{ - MysqlConn* conn = new MysqlConn; - bool res = conn->connect(m_user, m_passwd, m_dbName, m_ip, m_port); - if (res) { - // 刷新空闲时间 - conn->refreashAliveTime(); - m_connections.push(conn); - ++m_num; - return true; - } - else { - delete conn; - return false; // 提示 - } + +void ConnectionPool::produce() { + while (true) { + unique_lock<mutex> lock(m_mutex); + while (m_connkQueue.size() >= m_min_conn) { // 连接队列的数量大于最小的连接数 + m_cond.wait(lock); + } + addConnection(); + } } -void ConnectionPool::productConnection() -{ - while (true) { - unique_lock<mutex> lc(m_mutex); - m_cond.wait(lc, [this]() {return m_connections.empty(); }); - if (m_num < m_maxSize) { - bool flag = addConnection(); - if (!flag) { - return; - } - } - // 唤醒 - m_cond1.notify_all(); - } + +// 删除空闲连接 +void ConnectionPool::recycle() { + while (true) { + this_thread::sleep_for(chrono::milliseconds(500)); // 休眠 500 ms + unique_lock<mutex> lock(m_mutex); + while (m_connkQueue.size() > m_min_conn) { + MysqlConn* conn = m_connkQueue.front(); + if (conn->getActiveTime() >= max_del_time) { + m_connkQueue.pop(); + delete conn; + } + else { + break; + } + } + } } -void ConnectionPool::recycleConnection() -{ - while (true) { - // 休眠一段时间 0.5s - this_thread::sleep_for(milliseconds(500)); - lock_guard<mutex> lc(m_mutex); - while (!m_connections.empty() && m_num > m_minSize) { - MysqlConn* conn = m_connections.front(); - if (conn->getAliveTime() >= m_maxIdleTime) { - m_connections.pop(); - delete conn; - --m_num; - } - else { - break; - } - } - } + +shared_ptr<MysqlConn> ConnectionPool::getMysqlConn() { + unique_lock<mutex> lock(m_mutex); + while (m_connkQueue.empty()) { + // 如果等待一段时间后,队列还是为空,返回一个 null + if (cv_status::timeout == m_cond.wait_for(lock, chrono::milliseconds(m_timeout))) { + if (m_connkQueue.empty()) return nullptr; + } + } + shared_ptr<MysqlConn> connPtr(move(m_connkQueue.front()), [this](MysqlConn* conn) { + unique_lock<mutex> lock(m_mutex); + conn->refreshActiveTime(); + m_connkQueue.push(conn); + }); + m_connkQueue.pop(); + m_cond.notify_one(); // 唤醒阻塞的生产者线程,开始生产 + return connPtr; } -ConnectionPool* ConnectionPool::getConnectPool() -{ - // 不使用互斥锁的线程安全的懒汉模式 - static ConnectionPool pool; // 只在第一次调用函数时初始化 - return &pool; +void ConnectionPool::description() { + cout << m_ip << ". " << m_userName << ". " << m_passwd << ". " << m_db << ". " + << m_port << ". " << m_max_conn << ". " << m_min_conn << ". " << m_timeout << ". " + << max_del_time << endl; } -shared_ptr<MysqlConn> ConnectionPool::getConnection() -{ - unique_lock<mutex> lc(m_mutex); - while (m_connections.empty()) { - if (cv_status::timeout == m_cond1.wait_for(lc, chrono::milliseconds(m_timeout))) { - if (m_connections.empty()) { - // cout << "out of time" << endl; - return nullptr; // 结束 // 提示 - // continue; // 利用while配合continue 继续阻塞 - } - } - } - // 要指定删除器destructor,来保证连接的归还 - shared_ptr<MysqlConn> conn(m_connections.front(), [this](MysqlConn* conn) { - // 加锁保证队列线程安全 - // m_mutex.lock(); // 1 - unique_lock<mutex> lc(m_mutex); // 2 - // lock_guard<mutex> lc(m_mutex); // 3 - conn->refreashAliveTime(); - m_connections.push(conn); - // m_mutex.unlock(); // 1 - }); - m_connections.pop(); - m_cond.notify_all(); - return conn; -} + +ConnectionPool* ConnectionPool::getInstance() { + static ConnectionPool connPool; + return &connPool; +} \ No newline at end of file -- Gitblit v1.8.0