这个项目是一个老外在github上的一个项目(https://github.com/progschj/ThreadPool),使用c++11编写的,代码写的非常好,使用了很多c++11的新特性,例如ref,move,result_of,智能指针,线程的新写法,我自己加了一部分注解,如果没有学过C++11的新特性,可能会看不懂,不过我都加了注解。
#ifndef THREAD_POOL_H
#define THREAD_POOL_H
#include <thread>
#include <mutex>
#include <condition_variable>
#include <memory>
#include <queue>
#include <future>
#include <functional>
#include <stdexcept>
class ThreadPool
{
public:
ThreadPool(size_t); //做初始化操作
template <class F, class... Args>
auto enqueue(F &&f, Args &&...args) //将任务放入任务队列中
-> std::future<typename std::result_of<F(Args...)>::type>;
~ThreadPool(); //执行释放
private:
std::vector<std::thread> works; //存放线程
std::queue<std::function<void()>> tasks; //存放执行任务
std::mutex queue_mutex; //互斥量
std::condition_variable condition; //条件变量
bool stop; //控制整个线程池的运行状态
};
inline ThreadPool::ThreadPool(size_t threads) : stop(false)
{
for (size_t i = 0; i < threads; i++) //创建线程执行函数
{ //创建线程
works.emplace_back(
[this]() {
for(;;) {
std::function<void()> task;
{
std::unique_lock<std::mutex> lock(queue_mutex);
//条件为false的话,会阻塞
//下面stop==true时,说明线程池应该退出,此时不应该继续阻塞,所以下面加了一个if判断,可以直接返回
this->condition.wait(lock,
[this]
{ return stop == true || !this->tasks.empty(); });
if(stop == true || this->tasks.empty())
return;
task = std::move(this->tasks.front());
tasks.pop();
}
task();
}
});
}
}
//将任务放入任务队列中
template <class F, class... Args>
auto ThreadPool::enqueue(F &&f, Args &&...args)
-> std::future<typename std::result_of<F(Args...)>::type> //萃取返回值的类型,future中需要指明最终的返回值,而我们的返回值是根据任务函数而来的,需要使用result_of
{
using resultType = typename std::result_of<F(Args...)>::type; //返回值
//使用智能指针管理packaged_task,注意packaged_task一般需要和future配合使用,
// future一般可以返回结构线程需要返回的结果,需要将packaged_task绑定任务函数
auto task = std::make_shared<std::packaged_task<resultType()>>(
std::bind(std::forward<F>(f), std::forward<Args>(args)...));
std::future<resultType> res = task->get_future(); //与packaged_task绑定在一起
{ //放入任务队列中,手动加锁,也可以自己实现一个线程安全的队列
std::unique_lock<std::mutex> lock(queue_mutex);
if (stop)
throw std::runtime_error("enqueue on stopped ThreadPool");
tasks.emplace( // 放入lambda表达式,这个lambda用于线程执行的函数
[task]()
{
(*task)(); //task是可以直接调用的,会执行绑定时的函数,也就是我们任务
});
} //出了作用域会自动释放锁,这也是与lock_guard(需要手动释放锁)最大的不同
condition.notify_one(); //通知线程处理任务
return res;
}
// 释放资源
ThreadPool::~ThreadPool()
{
{
std::unique_lock<std::mutex> lock(queue_mutex);
stop = true;
}
condition.notify_all();
for (std::thread &item : works)
item.join();
}
#endif
测试代码
#include <iostream>
#include <vector>
#include <chrono>
#include "myThreadPool.h"
int main()
{
ThreadPool pool(4); // 创建4个线程
std::vector< std::future<int> > results;
for(int i = 0; i < 8; ++i) {
// 往pool中放入需要执行的任务,返回异步future来接收结果
results.emplace_back(
pool.enqueue([i] {
std::cout << "hello " << i << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "world " << i << std::endl;
return i*i;
})
);
}
std::cout << results.size();
for(auto && result: results)
std::cout << result.get() << ' ';
std::cout << std::endl;
return 0;
}