转载自:
https://blog.csdn.net/u013507368/article/details/48130151?utm_source=blogxgwz0
#pragma once
#include <iostream>
#include <deque>
#include <thread>
#include <mutex>
#include <functional>
#include <condition_variable>
#include <vector>
#include <memory>
#include <string>
class ThreadPool
{
public:
typedef std::function<void()> Task;
explicit ThreadPool(const std::string &name = std::string());
~ThreadPool();
//set threads num
void start(int numThreads);
//stop all threads
void stop();
//run task f in thread pool
void run(const Task &f);
//set max thread queue size
void setMaxQueueSize(int maxSize) { _maxQueueSize = maxSize; }
private:
//copy constructor
ThreadPool(const ThreadPool& x) = delete;
//assgine
ThreadPool& operator=(const ThreadPool& x) = delete;
//if task queue is full
bool isFull();
//function used to run the task for a thread
void runInThread();
//get task from the queue
Task take();
std::mutex _mutex;
std::condition_variable _notEmpty;
std::condition_variable _notFull;
std::string _name;
std::vector<std::thread> _threads;
std::deque<Task> _queue;
int _maxQueueSize;
bool _running;
};
#include "ThreadPool.hpp"
#include <cassert>
ThreadPool::ThreadPool(std::string const &name) :
_name(name),
_maxQueueSize(0),
_running(false)
{
}
ThreadPool::~ThreadPool()
{
if (_running)
{
stop();
}
}
void ThreadPool::start(int numThreads)
{
assert(_threads.empty());
_running = true;
_threads.reserve(numThreads);
for (int i = 0; i < numThreads; ++i)
{
_threads.push_back(std::thread(&ThreadPool::runInThread, this));
}
}
void ThreadPool::stop()
{
{
std::unique_lock<std::mutex> lock(_mutex);
_running = false;
_notEmpty.notify_all();
}
for (int i = 0; i < _threads.size(); ++i)
{
_threads[i].join();
}
}
//这里只是将任务放入到队列,并不直接run,而是通知thread vector中的线程来获取这个任务并执行
void ThreadPool::run(const Task &f)
{
if (_threads.empty())
{
f();
}
else
{
std::unique_lock<std::mutex> lock(_mutex);
while (isFull())
{
_notFull.wait(lock);
}
assert(!isFull());
_queue.push_back(f);
_notEmpty.notify_one();
}
}
ThreadPool::Task ThreadPool::take()
{
std::unique_lock<std::mutex> lock(_mutex);
while (_queue.empty() && _running)
{
_notEmpty.wait(lock);
}
Task task;
if (!_queue.empty())
{
task = _queue.front();
_queue.pop_front();
if (_maxQueueSize > 0)
{
_notFull.notify_one();
}
}
return task;
}
bool ThreadPool::isFull()
{
return _maxQueueSize > 0 && _queue.size() >= _maxQueueSize;
}
//从任务队列中取出task并且执行
void ThreadPool::runInThread()
{
try
{
while (_running)
{
Task task = take();
if (task)
{
task();
}
}
}
catch (const std::exception & ex)
{
fprintf(stderr, "exception caught in ThreadPool %s\n", _name.c_str());
fprintf(stderr, "reason: %s\n", ex.what());
abort();
}
catch (...)
{
fprintf(stderr, "exception caught in ThreadPool %s\n", _name.c_str());
}
}
#include<thread>
#include<chrono>
#include "ThreadPool.hpp"
void Test(int i)
{
while (true)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "threadId:" << std::this_thread::get_id() << std::endl;
}
}
int main()
{
ThreadPool threadPool;
threadPool.setMaxQueueSize(10);
threadPool.start(5);
for (int i = 0; i < 10; ++i)
{
auto task = std::bind(Test, i);
threadPool.run(task);
}
return 0;
}