时间:2021-05-20
最近自己写了一个线程池。
总的来说,线程池就是有一个任务队列,一个线程队列,线程队列不断地去取任务队列中的任务来执行,当任务队列中为空时,线程阻塞等待新的任务添加过来。
我是用queue来存放任务,vector存放thread*,然后用condition_variable 来设置线程阻塞和唤醒。
下面直接上代码吧。
线程池类头文件Thread_Pool.h
/******************************************** 线程池头文件 Author:十面埋伏但莫慌 Time:2020/05/03*********************************************/#pragma once#ifndef _THREAD_POOL_H_#define _THREAD_POOL_H_#include<thread>#include<queue>#include<mutex>#include<atomic>#include<vector>#include<condition_variable>typedef std::function<void()> Func;//定义线程执行函数类型,方便后面编码使用。//任务类class Task {public: Task() {} ~Task() {} int push(Func func);//添加任务; int getTaskNum();//获得当前队列中的任务数; Func pop();//取出待执行的任务;public: std::mutex mx;//锁;private: std::queue<Func> tasks;//任务队列};//线程池类class Thread_Pool {public: Thread_Pool() :IsStart(false) {} ~Thread_Pool(); int addTasks(Func tasks);//添加任务; void start();//开启线程池; void stop();//关闭线程池; void run();//线程工作函数; int getTaskNum();//获得当前队列中的任务数;private: static const int maxThreadNum = 3;//最大线程数为3; std::condition_variable cond;//条件量; std::vector<std::thread*> threads;//线程向量; std::atomic<bool> IsStart;//原子变量,判断线程池是否运行; Task tasks;//任务变量;};#endif然后是线程池类成员函数定义文件Thread_Pool.cpp
/******************************************** 线程池CPP文件 Author:十面埋伏但莫慌 Time:2020/05/03*********************************************/#include"Thread_Pool.h"#include<iostream>int Task::push(Func func) { std::unique_lock<std::mutex> lock(mx); try { tasks.emplace(func); } catch (std::exception e) { throw e; return -1; } return 0;}int Task::getTaskNum(){ return tasks.size();}Func Task::pop() { std::unique_lock<std::mutex> lock(mx); Func temp; if (tasks.empty()) return temp; else { temp = tasks.front(); tasks.pop(); return temp; }}int Thread_Pool::addTasks(Func func){ int ret = tasks.push(func); cond.notify_one(); return ret;}void Thread_Pool::start() { if (!IsStart) { IsStart = true; for (int i = 0; i < maxThreadNum; i++) { threads.emplace_back(new std::thread(std::bind(&Thread_Pool::run,this))); } }}void Thread_Pool::run(){ while (IsStart) { Func f; if (tasks.getTaskNum() == 0 && IsStart) { std::unique_lock<std::mutex> lock(tasks.mx); cond.wait(lock); } if (tasks.getTaskNum() != 0 && IsStart) { f = tasks.pop(); if(f) f(); } }}int Thread_Pool::getTaskNum() { return tasks.getTaskNum();}void Thread_Pool::stop() { IsStart = false; cond.notify_all(); for (auto T : threads) { std::cout << "线程 " << T->get_id() << " 已停止。" << std::endl; T->join(); if (T != nullptr) { delete T; T = nullptr; } } std::cout << "所有线程已停止。" << std::endl;}Thread_Pool::~Thread_Pool() { if (IsStart) { stop(); }}最后是测试用的main.cpp
#include<iostream>#include"Thread_Pool.h"using namespace std;void string_out_one() { cout << "One!" << endl;}void string_out_two() { cout << "Two!" << endl;}void string_out_three() { cout << "Three!" << endl;}int main() { { Thread_Pool Pool; try { Pool.start(); } catch (std::exception e) { throw e; cout << "线程池创建失败。" << endl; } for (int i = 0; i < 50000 ;) { if (Pool.getTaskNum() < 1000) { Pool.addTasks(string_out_one); Pool.addTasks(string_out_two); Pool.addTasks(string_out_three); std::cout << i++ << std::endl; } } getchar(); } getchar(); return 0;}执行的效果如下:
线程唤醒和阻塞的逻辑就是在线程工作函数run函数中,判断队列是否为空,若为空则设置锁并调用condition变量的wait函数,释放这个线程中的锁并阻塞线程,等待任务队列中新的任务添加进来后,
condition变量通过notify_one()随机唤醒一个在wait的线程,取出队列中的任务执行。
写这个线程池的过程中碰到的最主要需要注意的就是锁的使用,在对队列的写和释放时要注意加锁,在需要阻塞线程时,要注意通过{}设置锁的范围。
IsStart是原子的,所以在写这个变量的时候没有另外加锁。
目前我觉得这个线程池的缺陷就是可执行函数的类型被写死了,有尝试对Task类使用模板类,但是在Thread_Pool中还是要指明Task模板类的类型参数,要是有大神指点下就好了- -。
就先记录这么多,感觉这个线程池的还是有很多可以改进的地方的,也欢迎大家指出不足。
到此这篇关于C++实现线程池的简单方法的文章就介绍到这了,更多相关C++实现线程池内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
本文以实例形式较为详细的讲述了C++线程池的简单实现方法。分享给大家供大家参考之用。具体方法如下:一、几个基本的线程函数:1.线程操纵函数:intpthread
线程池示例在分析线程池之前,先看一个简单的线程池示例。importjava.util.concurrent.Executors;importjava.util.
本文实例讲述了c++线程池实现方法。分享给大家供大家参考。具体分析如下:下面这个线程池是我在工作中用到过的,原理还是建立一个任务队列,让多个线程互斥的在队列中取
本文实例讲述了基于C++实现的线程休眠代码,分享给大家供大家参考。具体方法如下:linux平台示例如下:/*File:thread1.cAuthor:MikeE
本文实例讲述了C++使用CriticalSection实现线程同步的方法,在前文C++线程同步实例分析的基础上增加了四行代码,使用了四个函数:EnterCrit