1、三大类
- 任务类Task
- 任务队列TaskQueue
- 线程池ThreadPool
2、任务类Task
#pragma once
#include <functional>
using namespace std;
template<class T>
struct Task
{
public:
Task()
{
}
Task(function<void(T)> function, T args) : m_function(function), m_args(args)
{
}
void exec()
{
m_function(m_args);
}
private:
function<void(T)> m_function;
T m_args;
};
};
3、任务队列TaskQueue
#pragma once
#include "Task.h"
#include <queue>
#include <mutex>
template<class T>
class TaskQueue
{
public:
TaskQueue()
{
}
void addTask(const Task<T> & task)
{
m_QueMutex.lock();
m_QueTaskQueue.push(task);
m_QueMutex.unlock();
}
Task<T> takeTask()
{
Task<T> t;
m_QueMutex.lock();
if (m_QueTaskQueue.size() > 0)
{
t = m_QueTaskQueue.front();
m_QueTaskQueue.pop();
}
m_QueMutex.unlock();
return t;
}
int taskSize()
{
int size_now;
m_QueMutex.lock();
size_now = m_QueTaskQueue.size();
m_QueMutex.unlock();
return size_now;
}
bool taskEmpty()
{
bool empty;
m_QueMutex.lock();
empty = m_QueTaskQueue.empty();
m_QueMutex.unlock();
return empty;
}
void executeTasks()
{
m_QueMutex.lock();
if (!m_QueTaskQueue.empty())
{
cout << " " << this_thread::get_id() << "\t";
Task<T> t = m_QueTaskQueue.front();
m_QueTaskQueue.pop();
t.exec();
}
m_QueMutex.unlock();
}
private:
queue<Task<T>> m_QueTaskQueue;
std::mutex m_QueMutex;
};
4、线程池类
#include "TaskQueue.h"
#include <iostream>
#include <condition_variable>
#include <thread>
#include <vector>
#include <functional>
#include <memory>
template<class T>
class ThreadPool
{
public:
ThreadPool(const int &min, const int &max, int check_sec = 5)
: m_minNum(min), m_maxNum(max), m_checkSec(check_sec),
m_shutdown(false), m_toBeExitNum(0),
m_aliveNum(min), m_busyNum(0)
{
m_TaskQueue = std::make_unique<TaskQueue<T>>();
m_threads.reserve(max);
for (int i = 0; i < m_minNum; i++)
{
m_threads.emplace_back(&ThreadPool::work, this);
std::cout << m_threads.back().get_id() << " 线程创建成功" << std::endl;
}
m_manager = std::thread(&ThreadPool::managerWork, this);
}
~ThreadPool()
{
m_shutdown = true;
m_manager.join();
for (auto &thread : m_threads)
{
m_cond.notify_one();
thread.join();
}
cout << "线程池销毁" << endl;
}
void addTask(const Task<T> task)
{
if (m_shutdown)
return;
m_TaskQueue->addTask(task);
m_cond.notify_one();
}
int getBusyNum()
{
std::unique_lock<std::mutex> lock(m_mutex);
return m_busyNum;
}
int getAliveNum()
{
std::unique_lock<std::mutex> lock(m_mutex);
return m_aliveNum;
}
int getTaskNum()
{
std::unique_lock<std::mutex> lock(m_mutex);
return m_TaskQueue->taskSize();
}
private:
void work()
{
while (true)
{
std::unique_lock<std::mutex> lock(m_mutex);
while (m_TaskQueue->taskEmpty() && !m_shutdown)
{
m_cond.wait(lock);
if (m_toBeExitNum > 0)
{
m_toBeExitNum--;
if (m_aliveNum > m_minNum)
{
m_aliveNum--;
return;
}
}
}
if (m_shutdown)
{
return;
}
Task<T> task = m_TaskQueue->takeTask();
m_busyNum++;
lock.unlock();
task.exec();
lock.lock();
m_busyNum--;
}
}
void managerWork()
{
while (!m_shutdown)
{
std::this_thread::sleep_for(std::chrono::seconds(m_checkSec));
std::unique_lock<std::mutex> lock(m_mutex);
int taskNum = m_TaskQueue->taskSize();
int liveNum = m_aliveNum;
int busyNum = m_busyNum;
if (taskNum > liveNum && liveNum < m_maxNum)
{
int toNum = std::min(taskNum - liveNum, m_maxNum - liveNum);
for (int i = 0; i < toNum; i++)
{
m_threads.emplace_back(&ThreadPool::work, this);
m_aliveNum++;
}
}
if (busyNum * 2 < liveNum && liveNum > m_minNum)
{
int num = std::min((liveNum - m_minNum + 1) / 2, liveNum - m_minNum);
m_toBeExitNum = num;
lock.unlock();
for (int i = 0; i < num; i++)
{
m_cond.notify_one();
}
}
lock.unlock();
}
}
private:
std::unique_ptr<TaskQueue<T>> m_TaskQueue;
std::vector<std::thread> m_threads;
std::thread m_manager;
int m_minNum;
int m_maxNum;
int m_busyNum;
int m_aliveNum;
int m_toBeExitNum;
bool m_shutdown;
int m_checkSec;
std::condition_variable m_cond;
std::mutex m_mutex;
};
5、测试
#include <iostream>
using namespace std;
#include <string>
#include <thread>
#include "ThreadPool.h"
class Task_
{
public:
void operator()(initializer_list<string> arg)
{
this_thread::sleep_for(chrono::seconds(2));
for (auto it = arg.begin(); it != arg.end(); it++)
{
cout << *it << "\t";
}
cout << endl;
}
};
void test_task()
{
initializer_list<string> lis1 = { "java", "c" };
Task<initializer_list<string>> task1(Task_(), lis1);
initializer_list<string> lis2 = { "python", "c" };
Task<initializer_list<string>> task2(Task_(), lis2);
initializer_list<string> lis3 = { "golang", "c" };
Task<initializer_list<string>> task3(Task_(), lis3);
ThreadPool<initializer_list<string>> pool(3, 6);
pool.addTask(task1);
pool.addTask(task2);
pool.addTask(task3);
this_thread::sleep_for(chrono::milliseconds(300));
int i = 0;
while (true)
{
cout << "正在忙碌中的线程数量 -> " << pool.getBusyNum() << endl;
cout << "存活状态中的线程数量 -> " << pool.getAliveNum() << endl;
cout << "当前任务数 -> " << pool.getTaskNum() << endl;
this_thread::sleep_for(chrono::seconds(3));
for (int i = 0; i < 6; i++)
{
pool.addTask(task3);
}
i++;
if (i == 8)
{
break;
}
}
}
int main(int argc, char * argv[])
{
test_task();
system("pause");
return 0;
}