C++ 线程池

在C++中,线程池是一种用于管理和复用线程的机制,以减少线程创建和销毁的开销,并提高系统的响应速度和吞吐量。下面是一个简单的C++线程池实现的概述:

线程池设计

线程池大小:确定线程池中线程的数量。

任务队列:用于存储待执行的任务。

线程管理:创建、启动、管理和销毁线程。

任务调度:从任务队列中取出任务并分配给空闲线程执行。

示例如下:

cpp 复制代码
#pragma once
#include <iostream>  
#include <vector>  
#include <queue>  
#include <thread>  
#include <mutex>  
#include <condition_variable>  
#include <functional>  
#include <future> 


class ThreadPool
{
public:
	ThreadPool(size_t count);
	~ThreadPool();
	ThreadPool(const ThreadPool&) = delete; //禁用拷贝构造
	const ThreadPool& operator=(const ThreadPool&) = delete; //禁用赋值运算符
	void threadLoop();
	void addTask(std::function<void()> &task);

private:
	std::vector<std::thread*> _threads;
	std::queue<std::function<void()>> _tasks;
	std::mutex _mtx;
	std::condition_variable _cv;
	bool _stop;
};
cpp 复制代码
#include "ThreadPool.h"

ThreadPool::ThreadPool(size_t count): _stop(false)
{
	_threads.reserve(count);
	for (size_t i = 0; i < count; ++i)
	{
		_threads.emplace_back(
			new std::thread(std::bind(&ThreadPool::threadLoop, this))
		);
	}
}

ThreadPool::~ThreadPool()
{
	std::unique_lock<std::mutex> lock(_mtx);
	_stop = true;
	_cv.notify_all();
	for (auto it = _threads.begin(); it != _threads.end(); ++it)
	{
		(*it)->join();
		delete *it;
	}
	_threads.clear();
}

void ThreadPool::threadLoop()
{
	while (!_stop)
	{
		std::unique_lock<std::mutex> lock(_mtx);
		if(_tasks.empty())
			_cv.wait(lock);
		if (!_tasks.empty())
		{
			std::function<void()> task = _tasks.front();
			_tasks.pop();
			task();  //执行任务
		}
	}
}

void ThreadPool::addTask(std::function<void()> &task)
{
	std::unique_lock<std::mutex> lock(_mtx);
	_tasks.emplace(task);
	_cv.notify_one();
}

Qt线程池:

Qt 提供了一个线程池(QThreadPool)来简化多线程编程。只需将任务(通常是以 QRunnable 或其子类形式的任务)提交给线程池,然后由线程池自动处理任务的分配和执行。

以下是使用 Qt 线程池的基本步骤:

1、包含必要的头文件

cpp 复制代码
#include <QThreadPool>  
#include <QRunnable>

2、创建自定义任务

创建一个继承自 QRunnable 的类,并实现 run() 方法。这个方法将包含你的任务代码。

cpp 复制代码
class MyTask : public QRunnable  
{  
public:  
    void run() override {  
        // 在这里编写你的任务代码  
    }  
};

3、提交任务到线程池

使用 QThreadPool::globalInstance() 获取全局线程池的实例,然后调用 start() 方法来提交任务。

cpp 复制代码
MyTask *task = new MyTask();  
QThreadPool::globalInstance()->start(task);  
// 注意:task 对象将在任务完成后自动删除,除非你设置了不同的删除策略

4、配置线程池

你可以使用 QThreadPool 的各种方法来配置线程池的行为,例如设置最大线程数:

cpp 复制代码
QThreadPool::globalInstance()->setMaxThreadCount(4); // 设置最大线程数为 4

5、处理任务结果

如果你的任务需要返回结果,你可以使用信号和槽机制来在任务完成时发送结果。在你的 QRunnable 子类中,当任务完成时发出一个信号,然后在需要的地方连接这个信号到一个槽。

6、线程安全

在多线程环境中编程时,确保你的代码是线程安全的。避免在多个线程中同时访问和修改共享数据,除非你已经采取了适当的同步措施(如互斥锁)。

7、清理和关闭

当应用程序关闭时,Qt 将自动清理和关闭线程池。然而,如果你需要手动关闭线程池或等待所有任务完成,你可以使用 QThreadPool 的相关方法。

注意:Qt 线程池非常适合处理简单的并行任务,但对于复杂的并发需求(如需要精确控制线程生命周期或同步的情况),你可能需要直接使用 QThread 或其他更底层的并发机制。

相关推荐
tudousisi22224 分钟前
8.25第二题训练
c++
星星.72229 分钟前
2026河南萌新联赛第六场(郑州大学)补题B、D、L、J、I
数据结构·c++·算法
witton1 小时前
xmake中将proto文件生成C/C++文件然后再编译链接进项目
c语言·c++·mingw·protobuf·xmake·protobuf-c·protoc-gen-c
牛油果子哥q1 小时前
C++异常处理万字详解:try-throw-catch机制、栈展开、标准异常体系、自定义异常、工程规范、内存泄漏避坑
开发语言·jvm·c++
艾莉丝努力练剑1 小时前
【AI大模型接入SDK】C++日志体系与spdlog封装的理论部分
开发语言·c++·ide·人工智能·学习·面试·trae
旖旎夜光2 小时前
LCR 173:在点名(二分查找) —— 题解
数据结构·c++·算法·leetcode·二分查找
Lazionr3 小时前
模板进阶:深入理解模板机制
c++·windows
豆沙沙包?10 小时前
C++~~~stack容器、queue容器、list容器(p45-P56)
c++·windows·list
Frank_refuel10 小时前
【C++八股】面向对象
开发语言·c++
h_a_o777oah10 小时前
【图论】Tarjan 缩点:解决有向图中环的问题
c++·算法·图论·acm·强连通分量·缩点·tarjan