C++11实现线程池
根据网友提出的思路略有改动-----已测试
#pragma once
#include<iostream>
#include<thread>
#include<list>
#include<algorithm>
#include<functional>
#include<typeinfo>
#include<mutex>
#include<future>
#include<atomic>
#include<condition_variable>
#include<memory>
//线程池
class ThreadPool
{
private:
//定义一个无参无返回值的function类型,此类型将用做任务的存储类型,所有传入的函数都将转换为此类型
using Task = std::function<void()>;
//最大线程数,根据需要在构造函数中设置,过大会引起上下文频繁切换
int threadNum;
//剩余可用线程数
std::atomic<int> usableThread;
//存放线程的容器
std::list<std::thread> pools;
//存放转换后的任务
std::list<Task> tasks;
//互斥量
std::mutex mu;
//阻塞条件
std::condition_variable cond;
//所有线程是否继续执行
std::atomic<bool> running;
public:
//线程池构造函数,maxThreadNum为最大线程数
ThreadPool(int maxThreadNum = 6):threadNum(maxThreadNum),usableThread(maxThreadNum)
{
running.store(true);
//创建线程
for (int i = 0; i < maxThreadNum; i++)
{
//创建线程,循环等待任务的执行
std::thread t([this]()
{
Task nowtask;//当前要执行的任务
//不断获取任务,不断执行
while (running.load())
{
//从任务容器中获取任务,如果没有任务则阻塞
{
std::unique_lock<std::mutex> locker(mu);
//等待,一直到有任务时
while (this->tasks.empty()&&running.load())
{
cond.wait(locker);
}
if (this->tasks.empty())//如果是running关闭
{
continue;
}
//取出任务
nowtask = std::move(this->tasks.front());
this->tasks.pop_front();
}
usableThread--;
nowtask();
usableThread++;
}
});
//把创建的线程放到线程池中 ,线程对象没有复制构造函数,只有移动构造函数
pools.emplace_back(std::move(t));
}
}
//析构函数
~ThreadPool()
{
running.store(false);
cond.notify_all();
//将所有线程资源释放
for (std::thread& th : pools)
{
if (th.joinable())
{
th.join();
}
}
}
//将传进来的函数转换为统一类型的函数
template<typename F,typename ... Args>
auto commit(F&& f, Args&& ...args)->std::future<decltype(f(args...))>
{
//获取传入函数的返回值类型
using RetType = decltype(f(args...));
//获取指向std::packaged_task<RetType()>的智能指针
std::shared_ptr<std::packaged_task<RetType( )> > task =
std::make_shared<std::packaged_task<RetType( )>>
(
std::bind(std::forward<F>(f), std::forward<Args>(args)...)
);
//获取智能指针task所指向packaged_task的future
std::future<RetType> future = task->get_future();
{
std::unique_lock<std::mutex> locker(mu);
//将一个无参,无返回值的函数放入任务队列中
tasks.emplace_back([task]() {(*task)(); });
}
cond.notify_one();
return future;
}
};