线程池技术是为了避免频繁的创建和销毁线程所带来的开销。
线程池是一个典型的生产者-消费者模型,用户将要执行的任务添加到任务队列,并通知线程池,线程池则唤醒其中的一个线程来处理任务。一个简单的c++线程池实现如下所示:
#include <iostream>
#include <vector>
#include <deque>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <atomic>
#include <unistd.h>
using namespace std;
class ThreadPool
{
public:
using TaskEntry = function<void ()>;
ThreadPool(int size)
{
running.store(false);
stopflag.store(false);
int enablecpunums = sysconf(_SC_NPROCESSORS_ONLN);
threadpoolsize = (size > 0 && size < enablecpunums) ? size : enablecpunums;
}
~ThreadPool()
{
if (running.load()) { stop(); }
}
void start()
{
running.store(true);
threadbuckets.reserve(threadpoolsize);
for (int i = 0; i < threadpoolsize; i++)
{
threadbuckets.emplace_back(new thread(bind(&ThreadPool::TaskInitEntry, this)));
}
}
void stop()
{
stopflag.store(true);
while (1)
{
threadpoolmutex.lock();
int n = taskbuckets.size();
threadpoolmutex.unlock();
if (0 == n) break;
usleep(500*1000);
}
running.store(false);
threadpoolconvar.notify_all();
for (int i = 0; i < threadpoolsize; i++)
{
threadbuckets[i]->join();
}
}
void run(TaskEntry task)
{
if (stopflag.load() || !running.load() || !task) return;
unique_lock<mutex> lock(threadpoolmutex);
taskbuckets.push_back(task);
threadpoolconvar.notify_one();
}
private:
void TaskInitEntry()
{
while (running.load())
{
unique_lock<mutex> lock(threadpoolmutex);
threadpoolconvar.wait(lock, [this]{ return !running.load() || !taskbuckets.empty(); });
if (!running.load() && taskbuckets.empty()) return;
TaskEntry task = taskbuckets.front();
taskbuckets.pop_front();
task();
}
}
private:
atomic<bool> running;
atomic<bool> stopflag;
mutex threadpoolmutex;
int threadpoolsize;
condition_variable threadpoolconvar;
vector<unique_ptr<thread>> threadbuckets;
deque<TaskEntry> taskbuckets;
};
int main()
{
ThreadPool threadpool(8);
threadpool.start();
for (int i = 0; i < 100; i++)
{
threadpool.run([]{ cout << "abcdefg\n"; });
}
threadpool.stop();
return 0;
}
参考资料:
- muduo ThreadPool源码
- https://github.com/progschj/ThreadPool/blob/master/ThreadPool.h