目录
1.线程池 and 数据库连接池
2.生产者,消费者问题
3.排序算法
1.线程池 and 数据库连接池
线程池
#include <iostream>
#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>class ThreadPool
{
public:ThreadPool(size_t numThreads) : stop(false){for (size_t i = 0; i < numThreads; ++i){workers.emplace_back([this]{while (true) {std::function<void()> task;{std::unique_lock<std::mutex> lock(queueMutex);condition.wait(lock, [this] { return stop || !tasks.empty(); });if (stop && tasks.empty()) return;task = tasks.front();tasks.pop();}//取出任务队列中执行该任务task();} });}}template <class F>void enqueue(F &&f){{std::unique_lock<std::mutex> lock(queueMutex);tasks.emplace(std::forward<F>(f));}condition.notify_one();}~ThreadPool(){{std::unique_lock<std::mutex> lock(queueMutex);stop = true;}condition.notify_all();for (std::thread &worker : workers){worker.join();}}private:std::vector<std::thread> workers;std::queue<std::function<void()>> tasks;std::mutex queueMutex;std::condition_variable condition;bool stop;
};int main()
{ThreadPool pool(4);for (int i = 0; i < 8; ++i){pool.enqueue([i]{ std::cout << "Task " << i << " executed by thread " << std::this_thread::get_id() << std::endl; });}this_thread::sleep_for(chrono::seconds(1));system("pause");return 0;
}
说明:
1. **初始化线程池**:在创建线程池对象时,通过构造函数指定线程池中的线程数量。线程池会创建相应数量的工作线程,并启动这些线程等待任务。
2. **添加任务**:通过 `enqueue` 函数向线程池中添加任务。每个任务都是一个可调用对象,可以是函数、lambda 表达式或者其他可调用对象。添加任务时,会将任务移动到任务队列中,并通过条件变量通知等待中的工作线程有新任务可以执行。
3. **工作线程执行任务**:每个工作线程会循环执行以下操作:
- 等待条件变量的通知,一旦有新任务到来或者线程池被停止,就会被唤醒。
- 从任务队列中取出一个任务并执行。如果任务队列为空且线程池未被停止,线程会继续等待新任务的到来。
- 执行完任务后,继续循环等待新任务。
4. **停止线程池**:当需要销毁线程池时,调用析构函数或者手动调用停止函数。停止函数会将停止标志设置为 `true`,并通过条件变量通知所有工作线程线程池即将停止。
工作线程在收到停止通知后会执行完当前任务并退出线程。
5. **资源回收**:在线程池被销毁时,会等待所有工作线程执行完当前任务并回收资源。这包括等待所有工作线程结束并调用 `join` 函数等待线程结束。
数据库连接池
#include <iostream>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <thread>
#include <chrono>// 模拟数据库连接类
class Connection {
public:void executeQuery(const std::string& query) {std::cout << "Executing query: " << query << std::endl;// 模拟执行查询操作std::this_thread::sleep_for(std::chrono::seconds(1));}
};class ConnectionPool {
private:std::queue<Connection*> connections;std::mutex mtx;std::condition_variable cv;const int poolSize;public:ConnectionPool(int size) : poolSize(size) {for (int i = 0; i < poolSize; ++i) {connections.push(new Connection());}}Connection* getConnection() {std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, [this] { return !connections.empty(); });Connection* conn = connections.front();connections.pop();return conn;}void releaseConnection(Connection* conn) {std::lock_guard<std::mutex> lock(mtx);connections.push(conn);cv.notify_one();}~ConnectionPool() {while (!connections.empty()) {delete connections.front();connections.pop();}}
};int main() {ConnectionPool pool(5);// 从连接池中获取连接并执行查询Connection* conn1 = pool.getConnection();conn1->executeQuery("SELECT * FROM table1");pool.releaseConnection(conn1);// 可以继续获取连接并执行其他操作return 0;
}
-
Connection
类模拟了一个数据库连接,其中有一个executeQuery
方法用于执行查询操作。在这个方法中,会输出要执行的查询语句,并通过std::this_thread::sleep_for
来模拟查询操作需要的时间。 -
ConnectionPool
类是连接池类,其中包含了一个连接队列connections
,一个互斥锁mtx
用于保护对连接队列的访问,一个条件变量cv
用于在连接队列为空时等待新连接的到来,以及连接池的大小poolSize
。 -
在
ConnectionPool
的构造函数中,会初始化指定数量的连接对象并放入连接队列中。 -
getConnection
方法用于从连接池中获取连接。首先会对互斥锁进行加锁,然后通过条件变量等待直到连接队列不为空。一旦有可用连接,就从队列中取出一个连接并返回。 -
releaseConnection
方法用于释放连接,将连接放回连接队列中,并通过条件变量通知等待的线程有新的连接可用。 -
在
main
函数中,首先创建了一个大小为5的连接池pool
。然后从连接池中获取一个连接conn1
,执行了一个查询操作,最后通过releaseConnection
方法将连接放回连接池中。
这样,通过连接池可以有效地管理数据库连接,避免频繁地创建和销毁连接,提高了数据库操作的效率和性能。
2.生产者,消费者问题
#include <iostream>
#include <thread>
#include <vector>
#include <queue>
#include <mutex>
#include <condition_variable>
using namespace std;
#define PRODUCT_SIZE 2
#define CUSTUM_SIZE 2
#define POOL_SIZE 3
mutex m;
condition_variable cv;
queue<int> que;
int num = 0;//生产者线程。
void producter()
{while (true){std::unique_lock<std::mutex> lck(m);while (que.size() >= POOL_SIZE){cv.wait(lck);}int data = num++;que.push(data);cout << this_thread::get_id() << "produce " << data << endl;cv.notify_all();}
}
void customer()
{while (true){std::unique_lock<std::mutex> lck(m);while (que.empty()){cv.wait(lck);}cout << this_thread::get_id() << "consume " << que.front() << endl;que.pop();cv.notify_all();}
}int main()
{vector<thread> pools;//将生产者线程加入线程容器中。for (int i = 0; i < PRODUCT_SIZE; i++){pools.push_back(thread(producter));}//将消费者线程加入线程容器中。for (int j = 0; j < CUSTUM_SIZE; j++){pools.push_back(thread(customer));}//等待线程池中,所有线程都执行完毕。for (int i = 0; i < PRODUCT_SIZE + CUSTUM_SIZE; i++){pools[i].join();}cin.get();return 0;
}
3.排序算法
冒泡排序:N个数需要进⾏N-1次冒泡,每次冒泡确定⼀个最⼤值位置。元素交换次数为原数组逆序度。
void bubbleSort(std::vector<int> &nums, int n)
{for (int i = 1; i < n; ++i){ // 冒泡次数bool is_swap = false;for (int j = 1; j < n - i + 1; ++j){if (nums[j] < nums[j - 1]){std::swap(nums[j], nums[j - 1]);is_swap = true;}}if (!is_swap)break;}
}
void insertSort(std::vector<int> &nums, int n)
{for (int i = 1; i < n; ++i){for (int j = i; j > 0 && nums[j] < nums[j - 1]; --j){std::swap(nums[j], nums[j - 1]);}}
}
void selectSort(std::vector<int> &nums, int n)
{for (int i = 0; i < n - 1; ++i){int k = i;for (int j = i + 1; j < n; ++j){if (nums[j] < nums[k]){k = j;}}std::swap(nums[k], nums[i]);}
}
int partition(vector<int> &v, int low, int high)
{int pivot = v[high];int index = low;for (int i = low; i < high; i++){if (v[i] < pivot){swap(v[index++], v[i]);}}swap(v[index], v[high]);return index;
}void quickSort(vector<int> &v, int low, int high)
{if (low < high){int index = partition(v, low, high);quickSort(v, low, index - 1);quickSort(v, index + 1, high);}}int main()
{vector<int> v = {1, 19, 97, 9, 17, 8};// vector<int> v = {1, 20, 2, 3, 4, 5};quickSort(v, 0, v.size() - 1);for (auto i : v){cout << i << endl;}system("pause");return 0;
}
void mergeSort(std::vector<int> &nums, int l, int r)
{if (l < r){int mid = l + (r - l) / 2;mergeSort(nums, l, mid);mergeSort(nums, mid + 1, r);vector<int> tmp(r - l + 1);int i = l, j = mid + 1;int k = 0;while (i <= mid && j <= r){if (nums[i] < nums[j]){tmp[k++] = nums[i++];}else{tmp[k++] = nums[j++];}}while (i <= mid){tmp[k++] = nums[i++];}while (j <= r){tmp[k++] = nums[j++];}for (int p = 0; p < k; ++p){nums[l + p] = tmp[p];}}
}
void heapify(vector<int> &nums, int f, int n)
{int left = f * 2 + 1;int right = left + 1;while (left < n){int index = f;if (nums[index] < nums[left])index = left;if (right < n && nums[index] < nums[right])index = right;if (index == f){break;}else{swap(nums[f], nums[index]);f = index;left = f * 2 + 1;right = left + 1;}}
}
void heapSort(std::vector<int> &nums, int n)
{if (n < 2)return;// 从最后⼀个⽗节点调整为最⼤堆for (int i = n / 2 - 1; i >= 0; --i){heapify(nums, i, n);}// 最⼤值放最后,将剩下调整为堆for (int i = n - 1; i > 0; --i){std::swap(nums[0], nums[i]);heapify(nums, 0, i);}
}