#include <iostream>
#include <mutex>
#include <queue>
#include <vector>
#include <functional>
#include <condition_variable>
#include <atomic>
#include <chrono>
class ThreadPool
{
private:
std::queue<std::function<void()>> m_tasks;
std::vector<std::thread> m_threads;
std::thread m_threadManagement;
std::condition_variable cvTasksNotEmpty;
std::mutex mtxTasks;
std::mutex mtxThreads;
std::mutex mtxPoolFields;
bool m_shutdown;
int m_numMinThreads;
int m_numMaxThreads;
std::atomic<int> m_numCurThreads;
std::atomic<int> m_numBusyThreads;
std::atomic<int> m_numExitThreads;
const int THREADMANAGENUM = 2;
public:
ThreadPool(int min, int max) :m_threadManagement(ThreadPool::threadManage, this), m_numMinThreads(min < 1 ? 1 : min), m_numMaxThreads(max)
{
m_shutdown = false;
m_numCurThreads = m_numMinThreads;
m_numBusyThreads = 0;
m_numExitThreads = 0;
for (int i = 0; i < m_numCurThreads; i++)
{
std::unique_lock<std::mutex> ulThreads(mtxThreads);
m_threads.emplace_back([this]() {
m_numCurThreads.fetch_add(1, std::memory_order_relaxed);
threadTask();
});
}
}
ThreadPool(ThreadPool& another) = delete;
ThreadPool& operator=(ThreadPool& another) = delete;
~ThreadPool()
{
//析構銷燬執行緒池,釋放資源
m_shutdown = true;
cvTasksNotEmpty.notify_all(); //執行緒池要銷燬了。通知所有執行緒全部不阻塞向下執行
for (auto& item : m_threads)
{
item.join(); //等待全部執行緒return終止
}
m_threadManagement.join(); //等待管理執行緒終止
}
//子執行緒任務
void threadTask()
{
while (true)
{
std::unique_lock<std::mutex> ulTasks(mtxTasks);
cvTasksNotEmpty.wait(ulTasks, [=]() {
return !m_tasks.empty() || m_shutdown;
});
if (m_numExitThreads > 0)
{
m_numExitThreads.fetch_sub(1, std::memory_order_relaxed);
if (m_numCurThreads > m_numMinThreads)
{
m_numCurThreads.fetch_sub(1, std::memory_order_relaxed);
//關閉當前執行緒,從m_threads剔除
for (auto iter = m_threads.begin(); iter != m_threads.end();)
{
if (iter->get_id() == std::this_thread::get_id())
{
iter->detach();
std::unique_lock<std::mutex> ulThreads(mtxThreads);
iter = m_threads.erase(iter);
}
else
{
iter++;
}
}
return;
}
}
//判斷是否執行緒池被關閉,管理者執行緒不工作時m_threads中執行緒數固定,在析構中全部join(),閒置執行緒直接return終止
if (m_shutdown == true && m_tasks.empty())
{
return;
}
//取任務執行
std::function<void()> task(std::move(m_tasks.front()));
m_tasks.pop();
std::cout << "threadID=" << std::this_thread::get_id() << ",start working..." << std::endl;
ulTasks.unlock();
m_numBusyThreads.fetch_add(1, std::memory_order_relaxed);
task(); //執行緒執行任務
m_numBusyThreads.fetch_sub(1, std::memory_order_relaxed);
std::cout << "threadID=" << std::this_thread::get_id() << ",end working..." << std::endl; //執行緒執行完任務日誌輸出
}
}
//主執行緒新增任務。生產者
template<typename F, typename... Args>
void enqueue(F&& f, Args&&... args)
{
auto task = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
{
std::unique_lock<std::mutex> ulTasks(mtxTasks);
m_tasks.emplace(std::move(task));
}
cvTasksNotEmpty.notify_one();
}
//管理者執行緒任務
static void threadManage(ThreadPool* poolInstance);
};
void ThreadPool::threadManage(ThreadPool* poolInstance)
{
while (!poolInstance->m_shutdown)
{
std::this_thread::sleep_for(std::chrono::seconds(3));
std::unique_lock<std::mutex> ulTasks(poolInstance->mtxTasks);
int numTasks = static_cast<int>(poolInstance->m_tasks.size());
ulTasks.unlock();
//加執行緒
if (poolInstance->m_numCurThreads < poolInstance->m_numMaxThreads && poolInstance->m_numCurThreads < numTasks)
{
for (int i = 0; i < poolInstance->THREADMANAGENUM && poolInstance->m_numCurThreads < poolInstance->m_numMaxThreads; i++)
{
std::unique_lock<std::mutex> ulThreads(poolInstance->mtxThreads);
poolInstance->m_threads.emplace_back([poolInstance]() {
poolInstance->threadTask();
});
}
poolInstance->m_numCurThreads.fetch_add(1, std::memory_order_relaxed);
}
//減少執行緒
if (poolInstance->m_numBusyThreads * 2 < poolInstance->m_numCurThreads && poolInstance->m_numCurThreads > poolInstance->m_numMinThreads)
{
poolInstance->m_numExitThreads.store(poolInstance->THREADMANAGENUM);
//通知m_numExitThreads個阻塞的執行緒向下執行,就會退出
for (int i = 0; i < poolInstance->m_numExitThreads; i++)
{
poolInstance->cvTasksNotEmpty.notify_one();
}
}
}
}
std::mutex mtxfunc;
int data = 0;
void func()
{
for (int i = 0; i < 1000000; i++)
{
std::unique_lock<std::mutex> ul(mtxfunc);
data++;
}
}
int main()
{
auto start1 = std::chrono::steady_clock::now();
ThreadPool* tp = new ThreadPool(6,10);
tp->enqueue(func);
tp->enqueue(func);
tp->enqueue(func);
tp->enqueue(func);
tp->enqueue(func);
tp->enqueue(func);
delete tp;
auto end1 = std::chrono::steady_clock::now();
std::cout << "MainThreadID=" << std::this_thread::get_id() << ", final data= " << data << std::endl;
std::cout << "pool spend:" << std::chrono::duration_cast<std::chrono::microseconds>(end1 - start1).count() << "ms" << std::endl;
auto start2 = std::chrono::steady_clock::now();
for (int i = 0; i < 6000000; i++)
{
data++;
}
auto end2 = std::chrono::steady_clock::now();
std::cout << "mainthread spend:" << std::chrono::duration_cast<std::chrono::microseconds>(end2 - start2).count() << "ms" << std::endl;
std::cout << "MainThreadID=" << std::this_thread::get_id() << ", final data= " << data << std::endl;
}
效率比單執行緒低的多???