C++ 學(xué)習(xí)筆記實戰(zhàn)寫一個簡單的線程池示例
更新時間:2023年10月29日 15:57:16 作者:Totn
這篇文章主要為大家介紹了C++實現(xiàn)一個簡單的線程池學(xué)習(xí)實戰(zhàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
線程池的工作原理
- 在構(gòu)造函數(shù)中,創(chuàng)建指定數(shù)量的工作線程,并將它們存儲在
workers向量中。 - 每個工作線程都通過無限循環(huán)來執(zhí)行任務(wù)隊列中的任務(wù)。
- 設(shè)置一個
public函數(shù),接收新任務(wù),封裝為std::function<void()>并添加到任務(wù)隊列中。 - 等待的工作線程會被喚醒并獲取任務(wù)執(zhí)行,直到線程池被銷毀或調(diào)用
stop()函數(shù)停止。
第一步, 創(chuàng)建指定數(shù)量的工作線程
class ThreadPool {
public:
ThreadPool(int num){
// 啟動指定數(shù)量的線程
for(int i = 0; i < num; i++ ) {
// 使用循環(huán)創(chuàng)建指定數(shù)量的工作線程。每個工作線程都是通過`emplace_back`函數(shù)向`workers`容器中添加一個lambda函數(shù)創(chuàng)建的
// 添加一個lambda函數(shù)即為創(chuàng)建一個線程
workers.emplace_back([this]{
// code...
});
}
}
private:
// 用向量儲存線程
std::vector<std::thread> workers;
}第二步在每個線程中啟動死循環(huán),依次從任務(wù)隊列中取中任務(wù),直到隊列為空或設(shè)置stop標(biāo)識為true;
第二步,在第一步基礎(chǔ)上,添加代碼
class ThreadPool {
public:
ThreadPool(int num): stoped(false) {
// 啟動指定數(shù)量的線程
for(int i = 0; i < num; i++ ) {
// 使用循環(huán)創(chuàng)建指定數(shù)量的工作線程。每個工作線程都是通過`emplace_back`函數(shù)向`workers`容器中添加一個lambda函數(shù)創(chuàng)建的
// 添加一個lambda函數(shù)即為創(chuàng)建一個線程
workers.emplace_back([this]{
// 死循環(huán)
while(true) {
// 設(shè)置一個task接收從隊列中取出的任務(wù)
std::function<void()> task;
{
// 從隊列中取任務(wù)要加鎖,以避免重復(fù)讀
std::unique_lock<std::mutex> lock(ququeMutex);
// 如果stoped==true,或任務(wù)不為空,則使當(dāng)前線程等待
condition.wait(lock, [this]{ return stroped || !tasks.empty(); });
// 設(shè)置stoped為true后,則等到任務(wù)都完成為退出(tasks任務(wù)隊列為空)
if (stoped && tasks.empty()) {
return;
}
// 從隊列中接收任務(wù)
task = std::move(tasks.front());
// 彈出已經(jīng)接收的任務(wù)
tasks.pop();
}
// 以上代碼使用{}限制了作用域,在域內(nèi)啟用的鎖queueMutex在域結(jié)束后自動解鎖
}
});
}
}
// 設(shè)置停止標(biāo)識
void stop() {
std::unique_lock<std::mutex> lock(queueMutex);
stoped = true;
}
private:
// 用向量儲存線程
std::vector<std::thread> workers;
// 工作隊列
std::queue<std::function<void()> tasks;
// 隊列互斥鎖
std::mutex queueMutex;
// 條件變量
std::condition_variable condition;
// stop標(biāo)識
bool stoped;
}第三步,設(shè)置一個函數(shù)用從外部接收任務(wù)
// class ThreadBool...
template<class F>
void enqueue(F&& f){
{
// 在域內(nèi)啟用鎖, 保證加任務(wù)時沒沖突
std::unique_lock<std::mutex> lock(queueMutex);
// 轉(zhuǎn)發(fā)任務(wù)到tasks隊列中
tasks.emplace(std::forword<F>(f));
}
// 通知一個線程起來接活
condition.notify_one();
}
// ...第四步,設(shè)置析構(gòu)函數(shù)等待所有線程執(zhí)行完成
// class ThreadBool
~ThreadPool(){
?。?
std::unique_lock<std::mutex> lock(queueMutex);
stoded = true;
}
// 阻塞等待所有線程
for(std::thread& worker: workers){
worker.join();
}
}最后完整代碼
#include <vector>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <iostream>
thread_local int thr_num;
class Task{
public run(int num = 0) {
thr_num = num;
std::cout << "當(dāng)前任務(wù)號是" << thr_num << std::endl;
}
}
class ThreadPool {
public:
ThreadPool(int num): stoped(false) {
// 啟動指定數(shù)量的線程
for(int i = 0; i < num; i++ ) {
// 使用循環(huán)創(chuàng)建指定數(shù)量的工作線程。每個工作線程都是通過`emplace_back`函數(shù)向`workers`容器中添加一個lambda函數(shù)創(chuàng)建的
// 添加一個lambda函數(shù)即為創(chuàng)建一個線程
workers.emplace_back([this]{
// 死循環(huán)
while(true) {
// 設(shè)置一個task接收從隊列中取出的任務(wù)
std::function<void()> task;
{
// 從隊列中取任務(wù)要加鎖,以避免重復(fù)讀
std::unique_lock<std::mutex> lock(ququeMutex);
// 如果stoped==true,或任務(wù)不為空,則使當(dāng)前線程等待
condition.wait(lock, [this]{ return stroped || !tasks.empty(); });
// 設(shè)置stoped為true后,則等到任務(wù)都完成為退出(tasks任務(wù)隊列為空)
if (stoped && tasks.empty()) {
return;
}
// 從隊列中接收任務(wù)
task = std::move(tasks.front());
// 彈出已經(jīng)接收的任務(wù)
tasks.pop();
}
// 以上代碼使用{}限制了作用域,在域內(nèi)啟用的鎖queueMutex在域結(jié)束后自動解鎖
}
});
}
}
// 設(shè)置停止標(biāo)識
void stop() {
std::unique_lock(std::mutex )
stoped = true;
}
private:
// 用向量儲存線程
std::vector<std::thread> workers;
// 工作隊列
std::queue<std::function<void()> tasks;
// 隊列互斥鎖
std::mutex queueMutex;
// 條件變量
std::condition_variable condition;
// stop標(biāo)識
bool stoped;
}
int main() {
ThreadPool tp(4);
Task task;
for(int i = 0; i<4; i++) {
int num = i;
tp.enqueue([num, &task] {
task.run(num);
});
}
return 0;
}以上就是C++ 學(xué)習(xí)筆記實戰(zhàn)寫一個簡單的線程池示例的詳細內(nèi)容,更多關(guān)于C++ 線程池的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C語言項目小學(xué)生數(shù)學(xué)考試系統(tǒng)參考
今天小編就為大家分享一篇關(guān)于C語言項目小學(xué)生數(shù)學(xué)考試系統(tǒng)參考,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-02-02
C語言中的字符串?dāng)?shù)據(jù)在C中的存儲方式
這篇文章主要介紹了C語言中的字符串?dāng)?shù)據(jù)在C中的存儲方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07

