介绍
基于C++11标准实现的线程池,十分通用。支持不定参函数作为任务,核心功能已实现,细节功能可自行完善。原理不在赘述直接看代码。
代码
1、头文件
#ifndef THREADPOOL_H
#define THREADPOOL_H
#include <thread>
#include <mutex>
#include <queue>
#include <functional>
#include <condition_variable>
// 定义任务类型
typedef std::function<void()> Task;
class ThreadPool
{
public:
ThreadPool();
~ThreadPool();
//初始化线程池
void initThreadPool(int threadNum = 4);
//释放线程池
void releaseThreadPool();
//添加任务 方式1
void commitTask(Task task);
//添加任务 方式2
template <typename F, typename... Args>
void commitTaskEx(F &&f, Args && ... args)
{
Task task = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
{
std::lock_guard<std::mutex> lock(m_mutex);
m_tasks.emplace(task);
}
m_cond.notify_one();
}
public:
// 停止标志
bool m_stop;
private:
// 线程队列
std::vector<std::thread> m_workers;
// 任务队列
std::queue<Task> m_tasks;
// 互斥锁
std::mutex m_mutex;
// 条件变量
std::condition_variable m_cond;
};
#endif // THREADPOOL_H
2、实现文件
#include "threadpool.h"
ThreadPool::ThreadPool()
{
m_stop = false;
}
ThreadPool::~ThreadPool()
{
releaseThreadPool();
}
void ThreadPool::initThreadPool(int threadNum)
{
//定义线程执行函数
auto func = ([this]()
{
while(1)
{
Task task;
{
std::unique_lock<std::mutex> lock(this->m_mutex);
this->m_cond.wait(lock, [this] { return this->m_stop || !this->m_tasks.empty(); });
if (this->m_stop)
{
printf("thread stop id=%d\n", std::this_thread::get_id());
return;
}
task = std::move(this->m_tasks.front());
this->m_tasks.pop();
}
//执行任务
task();
}
});
//加入线程列表
for (int i=0; i<threadNum; ++i)
{
std::thread t(func);
m_workers.push_back(std::move(t));
}
}
void ThreadPool::releaseThreadPool()
{
{
std::unique_lock<std::mutex> lock(m_mutex);
m_stop = true;
}
m_cond.notify_all();
for(std::thread &worker: m_workers)
{
if(worker.joinable())
worker.join();
}
while(!m_tasks.empty())
m_tasks.pop();
}
void ThreadPool::commitTask(Task task)
{
{
std::lock_guard<std::mutex> lock(m_mutex);
m_tasks.emplace(task);
}
m_cond.notify_one();
}
使用测试
#include <iostream>
#include "threadpool.h"
void test1()
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
for (int i = 0; i < 5; i++)
{
printf("test1 i=%d id=%d\n", i, std::this_thread::get_id());
}
}
void test2(int a, int b, int c, std::string str)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
int ret = a + b + c;
for (int i = 0; i < 5; i++)
{
printf("%s i=%d %d id=%d\n", str.c_str(), i, ret, std::this_thread::get_id());
}
}
void test3(int a, const char *buf, std::string &str, bool &stop)
{
for (int i = 0; i < 5; i++)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
printf("%s a=%d i=%d %s id=%d\n", buf, a, i, str.c_str(), std::this_thread::get_id());
if(stop)
break;
}
}
int main()
{
printf("MainThread id=%d\n", std::this_thread::get_id());
ThreadPool pool;
pool.initThreadPool(4);
//添加任务1
auto testFunc = []() {test1(); };
pool.commitTask(testFunc);
//添加任务2
int a = 10;
int b = 20;
int c = 30;
std::string info = "lambda";
auto testFunc1 = [=](){test2(a, b, c, info);};
pool.commitTask(testFunc1);
//添加任务3
info = "templete";
pool.commitTaskEx(test2, a, b, c, info);
//添加任务4
char buf[10] = "test3";
std::string str = "ceshi123";
pool.commitTaskEx(test3, 4, buf, str, std::ref(pool.m_stop));
std::this_thread::sleep_for(std::chrono::milliseconds(6000));
return 0;
}
测试输出结果
>> 线程池线程数为1时
MainThread id=1
test1 i=0 id=2
test1 i=1 id=2
test1 i=2 id=2
test1 i=3 id=2
test1 i=4 id=2
lambda i=0 60 id=2
lambda i=1 60 id=2
lambda i=2 60 id=2
lambda i=3 60 id=2
lambda i=4 60 id=2
templete i=0 60 id=2
templete i=1 60 id=2
templete i=2 60 id=2
templete i=3 60 id=2
templete i=4 60 id=2
test3 a=4 i=0 ceshi123 id=2
test3 a=4 i=1 ceshi123 id=2
test3 a=4 i=2 ceshi123 id=2
test3 a=4 i=3 ceshi123 id=2
test3 a=4 i=4 ceshi123 id=2
thread stop id=2
>> 线程池线程数为4时
MainThread id=1
templete i=0 60 id=4
templete i=1 60 id=4
templete i=2 60 id=4
templete i=3 60 id=4
templete i=4 60 id=4
lambda i=0 60 id=3
lambda i=1 60 id=3
lambda i=2 60 id=3
lambda i=3 60 id=3
lambda i=4 60 id=3
test1 i=0 id=2
test1 i=1 id=2
test1 i=2 id=2
test1 i=3 id=2
test1 i=4 id=2
test3 a=4 i=0 ceshi123 id=5
test3 a=4 i=1 ceshi123 id=5
test3 a=4 i=2 ceshi123 id=5
test3 a=4 i=3 ceshi123 id=5
test3 a=4 i=4 ceshi123 id=5
thread stop id=4
thread stop id=3
thread stop id=5
thread stop id=2
自行测试其它场景,有问题可评论区交流指正。