C++实现的线程池

该文介绍了在Windows11环境下,使用C++17和VS2022开发的一个线程池库my_thread_pool。它支持FIFO和LIFO两种任务调度策略,任务调度通过接口Task_Control抽象,实现类包括Task_FIFO(先进先出)和Task_LIFO(先进后出)。线程池使用了互斥锁保证并发安全,并且计划通过插件模式扩展更多任务调度策略。在main.cpp中,展示了如何创建线程池并添加任务进行测试。

my_thread_pool

环境

  1. windows11

  2. C++17

  3. vs2022

思路

任务调度

  1. FIFO(先进先出)和LIFO(先进后出)。

  2. 以task_control为接口

class Task_Control
{
public:
    //添加任务
    virtual void Add_Task(Task task) = 0;
    //添加任务                   
    virtual void Add_Task(std::string name, callback f, void* arg) = 0;
    //取出任务       
    virtual Task take_Task() = 0;
    //返回任务数量                           
    virtual int return_task_number() = 0;
protected:
    Task_Control();
    ~Task_Control();
private:
};
  1. 以task_fifo和task_lifo继承接口并实现功能
//先进先出
class Task_FIFO :public Task_Control
{
public:
    //添加任务
    void Add_Task(Task task);
    //添加任务                   
    void Add_Task(std::string name, callback f, void* arg);
    //取出任务       
    Task take_Task();
    //返回任务数量                           
    int return_task_number();
protected:

private:
    std::queue<Task> Task_Queue;
    std::mutex m_mutex;    //互斥锁
};

//先进后出
class Task_LIFO :public Task_Control
{
public:
    //添加任务
    void Add_Task(Task task);
    //添加任务                   
    void Add_Task(std::string name, callback f, void* arg);
    //取出任务       
    Task take_Task();
    //返回任务数量                           
    int return_task_number();
protected:

private:
    std::stack<Task> Task_Stack;
    std::mutex m_mutex;    //互斥锁
};
  1. task_fifo实现用队列queue

  2. task_lifo实现用栈stack

  3. 以ioc容器来注册这两个接口类,方便线程池调用。

  4. 这个任务调度只用一把锁,需要改变或读取线程池内的私有量就上锁,完事后解锁。

  5. 未来实现

未来将利用插件模式,这样可以不局限于这两个接口,可以实现诸如随机取任务的类task_random.

线程池

  1. 指定任务调度方式,利用ioc容器,生成所需的任务调度.。
//注册任务调度
	ioc.registerType<Task_Control,Task_FIFO>("fifo");
	ioc.registerType<Task_Control, Task_LIFO>("lifo");

	//获取任务调度
	task_control = ioc.resolve<Task_Control>(control);
	if (task_control == nullptr)
	{
		std::cout << "error:没有:" << control << "类型的任务调度" << std::endl;
	}
  1. 指定工作线程数目,生成对应数量的工作线程
//创建工作线程
		for (int i = 0; i < thread_num; i++)
		{
			std::thread *Thread = new std::thread(worker,this);
			threadIDs[Thread->get_id()] = Thread;
		}
  1. 工作线程用hash表存放
std::unordered_map<std::thread::id, std::thread*> threadIDs;//存放工作线程
  1. 工作线程从任务容器中获取一个任务执行,任务执行完成后再取一个任务出来执行。没有任务就等待任务,除非收到结束指令。
		pool->m_mutex.lock();
		if (pool->shut_down == true)
		{
			pool->m_mutex.unlock();
			return;
		}
		if (pool->task_control->return_task_number() == 0)
		{
			pool->m_mutex.unlock();
			continue;
		}
		Task task = pool->task_control->take_Task();
		pool->busy_num++;
		pool->m_mutex.unlock();
		
		//执行任务
		task.fun(task.arg);

		printf("%s任务执行完成----------------by 工作thread: %d \n",task.name.c_str(),std::this_thread::get_id());

		delete task.arg;
		task.arg = NULL;

  1. 一个管理者线程

  2. 管理者线程每隔一秒判断是否需要关停线程池

while (true)
	{
		//每隔1秒检测一次
		std::this_thread::sleep_for(std::chrono::seconds(1));

		//获取数据
		pool->m_mutex.lock();
		std::string msg = "总线程数:" + std::to_string(pool->thread_num)
			+ " 当前忙碌线程数:" + std::to_string(pool->busy_num);
		std::cout << msg << std::endl;

		if (pool->busy_num == 0 && pool->task_control->return_task_number() == 0)
		{
			//下达关闭所有线程指令
			pool->shut_down = true;
			pool->m_mutex.unlock();
			return;
		}
		pool->m_mutex.unlock();
	}
  1. 整个线程池只用一把锁,需要改变或读取线程池内的私有量就上锁,完事后解锁。

代码文件

gitee地址

测试

  1. main.cpp
#include "Thread_Pool.h"
#include <iostream>
#include <string>
#include <windows.h>
void fun(void *arg)
{
    Sleep(3000);
}

int main()
{
    Thread_Pool tp(4, "lifo");

    for (int i = 0; i < 100; i++)
    {
        tp.addTask(Task(std::to_string(i),fun,nullptr));
    }
    std::cout << "ok\n";
    return 0;
}
  1. 结果

在这里插入图片描述
在这里插入图片描述

<think>好的,我现在需要帮助用户找到如何用C++实现线程池的示例代码或教程。首先,用户提到了他们之前看到的引用内容,里面有两个引用[^1]和[^2],都是关于C++线程池实现。我需要先仔细看看这两个引用里的内容,看看是否能直接提供代码或者教程的链接或具体步骤。 引用[1]中的代码示例展示了使用一个名为zThreadPool.h的头文件,主函数中创建了一个有4个线程的线程池,并添加了8个任务。任务函数是functionToRunInThread,它接收一个任务ID并打印线程ID和任务ID。看起来这个示例代码可能来自用户提到的某个教程或者项目,但用户提供的引用中没有给出更多的上下文或链接。不过代码本身已经比较完整,可以作为参考。 引用[2]则提到了另一个实现,其中定义了一个printTask任务,主函数创建了4个线程的线程池并提交了10个任务。同样,这里提到了stopPool函数来等待线程执行完毕。这可能意味着第二个实现有更完整的生命周期管理,比如启动和停止线程池的方法。 用户的需求是希望得到实现线程池的示例代码或教程。由于用户提供的引用中已经包含了部分代码,我应该将这些代码整理出来,并解释关键部分。同时,可能需要补充一些常见的实现步骤,比如线程池的基本结构、任务队列、工作线程的管理、同步机制(如互斥锁和条件变量)等。 接下来,我需要确保回答的结构清晰,分步骤说明如何实现线程池。首先,可能需要一个简单的实现示例,基于用户提供的引用代码,然后解释各部分的功能。此外,还需要提到一些优化方法或注意事项,比如异常处理、资源管理、任务调度策略等。 需要注意的是,用户可能对C++的线程库不太熟悉,所以代码示例中应该使用标准的C++11或更高版本的特性,比如std::thread、std::mutex、std::condition_variable等。同时,示例代码需要足够简洁,易于理解,但也要覆盖线程池的核心部分。 另外,用户可能希望了解如何添加任务到线程池中,以及如何正确关闭线程池,避免资源泄漏。引用中的代码没有展示线程池的停止机制,但引用[2]提到了stopPool函数,所以可能需要补充这部分内容,比如使用标志位通知线程退出,并join所有线程。 最后,根据用户的要求,生成相关问题。这些问题可能涉及线程池的工作原理、性能优化、任务调度策略、异常处理等,帮助用户进一步深入学习。 总结来说,我需要整理用户提供的代码示例,补充关键部分的解释,并给出一个完整的实现步骤,同时指出注意事项和优化建议。然后根据内容生成相关问题,帮助用户深化理解。</think>以下是一个基于C++11标准的线程池实现示例及解析,包含核心功能模块和代码注释: ```cpp #include <iostream> #include <vector> #include <queue> #include <thread> #include <mutex> #include <condition_variable> #include <functional> class ThreadPool { public: explicit ThreadPool(size_t threadNum) : stop(false) { for(size_t i = 0; i < threadNum; ++i) { workers.emplace_back([this] { for(;;) { std::function<void()> task; { std::unique_lock<std::mutex> lock(this->queueMutex); this->condition.wait(lock, [this]{ return this->stop || !this->tasks.empty(); }); if(this->stop && this->tasks.empty()) return; task = std::move(this->tasks.front()); this->tasks.pop(); } task(); } }); } } template<class F, class... Args> void enqueue(F&& f, Args&&... args) { { std::unique_lock<std::mutex> lock(queueMutex); tasks.emplace([=]{ f(args...); }); } 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; }; // 使用示例 void printTask(int taskId) { std::cout << "Thread " << std::this_thread::get_id() << " processing task " << taskId << std::endl; } int main() { ThreadPool pool(4); // 提交10个任务 for(int i = 0; i < 10; ++i) { pool.enqueue(printTask, i); } return 0; } ``` ### 实现解析 1. **线程管理** - 通过`std::vector<std::thread>`存储工作线程 - 构造函数中创建指定数量的工作线程,每个线程循环等待任务分配 2. **任务队列** - 使用`std::queue<std::function<void()>>`存储待执行任务 - 采用先进先出(FIFO)的任务调度策略 3. **同步机制** - `std::mutex`保护任务队列的并发访问 - `std::condition_variable`实现线程间的任务通知机制 4. **任务提交接口** - 模板方法`enqueue`支持任意参数型的任务提交 - 使用完美转发(perfect forwarding)保持参数型完整性 5. **安全关闭** - 析构函数中设置停止标志位 - 唤醒所有线程并等待任务完成 ### 优化建议 1. 增加任务优先级机制 2. 实现动态线程数量调整 3. 添加异常处理机制 4. 支持任务返回值的获取(可通过`std::future`实现
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱睡觉更爱学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值