#include <iostream>
#include <mutex>
#include <queue>
#include <vector>
#include <functional>
#include <condition_variable>
#include <atomic>
#include <chrono>
class ThreadPool
{
public:
ThreadPool(int num)
{
stopAll = false; //執行緒池物件停止標誌
m_numThreads = num < 1 ? 1 : num; //最少1個執行緒
for (int i = 0; i < m_numThreads; i++)
{
m_threads.emplace_back([=]() { //emplace_back移動語義,不複製
while (true)
{
std::unique_lock<std::mutex> ul(mtx); //互斥鎖,鎖住對共享變數m_tasks的訪問
cv.wait(ul, [=]() { //條件變數控制鎖ul的釋放、執行緒的阻塞和繼續
return !m_tasks.empty() || stopAll; //任務佇列非空或執行緒池停止則不阻塞,拿到ul
});
if (stopAll == true && m_tasks.empty()) //如果執行緒池停止執行緒立即return終止
{
return;
}
std::function<void()> task(std::move(m_tasks.front())); //從頭部取任務,移動語義減少複製,可呼叫物件包裝器包裝
m_tasks.pop(); //任務佇列彈出
ul.unlock(); //任務佇列訪問結束,解鎖放掉ul
std::cout << "threadID=" << std::this_thread::get_id() << ",start working..." << std::endl;
task(); //執行緒執行任務
std::cout << "threadID=" << std::this_thread::get_id() << ",end working..." << std::endl; //執行緒執行完任務日誌輸出
}
});
}
}
ThreadPool(ThreadPool& another) = delete; //禁用複製
ThreadPool& operator=(ThreadPool& another) = delete; //禁用operator=
~ThreadPool()
{
//析構銷燬執行緒池,釋放資源
std::unique_lock<std::mutex> ul(mtx); //要訪問共享變數stopAll(多個執行緒都訪問了stopAll),上鎖
stopAll = true; //執行緒池停止標誌置true
ul.unlock(); //stopAll訪問結束,解鎖
cv.notify_all(); //執行緒池要銷燬了。通知所有執行緒全部不阻塞向下執行
for (auto& item : m_threads)
{
item.join(); //等待全部執行緒return終止
}
}
//主執行緒新增任務。生產者
template<typename F, typename... Args>
void enqueue(F&& f, Args&&... args) //萬能引用
{
auto task = std::bind(std::forward<F>(f), std::forward<Args>(args)...); //f和args是萬能引用需要完美轉發,透過bind把引數繫結到函式f上
//區域性作用域,限定互斥鎖ul鎖定範圍
{
std::unique_lock<std::mutex> ul(mtx); //要訪問共享變數m_tasks,上鎖
m_tasks.emplace(std::move(task)); //任務佇列裡放1個任務,移動語義避免複製
}
cv.notify_one(); //放了個任務,解除1個執行緒的阻塞向下執行任務
}
private:
std::mutex mtx; //互斥量
std::condition_variable cv; //條件變數
bool stopAll;
int m_numThreads; //執行緒數
std::queue<std::function<void()>> m_tasks; //任務佇列。bind繫結了引數,所以function的模版型別是void()
std::vector<std::thread> m_threads; //執行緒容器
};
std::mutex mtxfunc;
int data;
void func()
{
std::unique_lock<std::mutex> ul(mtxfunc);
for (int i = 0; i < 1000000; i++)
{
data++;
}
}
int main()
{
auto start1 = std::chrono::steady_clock::now();
ThreadPool* tp = new ThreadPool(6);
tp->enqueue(func);
tp->enqueue(func);
tp->enqueue(func);
tp->enqueue(func);
tp->enqueue(func);
tp->enqueue(func);
auto end1 = std::chrono::steady_clock::now();
delete tp;
std::cout << "MainThreadID=" << std::this_thread::get_id() << ", final data= " << data << std::endl;
auto start2 = std::chrono::steady_clock::now();
std::cout << "pool spend:" << std::chrono::duration_cast<std::chrono::microseconds>(end1 - start1).count() << "ms" << std::endl;
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;
}