線程池學習

github看到一個項目(GitHub - markparticle/WebServer: C++ Linux WebServer服務器),內部使用的一個線程池看著不錯,拿來學習一下。

/** @Author       : mark* @Date         : 2020-06-15* @copyleft Apache 2.0*/ #ifndef THREADPOOL_H
#define THREADPOOL_H#include <mutex>
#include <condition_variable>
#include <queue>
#include <thread>
#include <functional>
class ThreadPool {
public:explicit ThreadPool(size_t threadCount = 8): pool_(std::make_shared<Pool>()) {assert(threadCount > 0);for(size_t i = 0; i < threadCount; i++) {std::thread([pool = pool_] {std::unique_lock<std::mutex> locker(pool->mtx);while(true) {if(!pool->tasks.empty()) {auto task = std::move(pool->tasks.front());pool->tasks.pop();locker.unlock();task();locker.lock();} else if(pool->isClosed) break;else pool->cond.wait(locker);}}).detach();}}ThreadPool() = default;ThreadPool(ThreadPool&&) = default;~ThreadPool() {if(static_cast<bool>(pool_)) {{std::lock_guard<std::mutex> locker(pool_->mtx);pool_->isClosed = true;}pool_->cond.notify_all();}}template<class F>void AddTask(F&& task) {{std::lock_guard<std::mutex> locker(pool_->mtx);pool_->tasks.emplace(std::forward<F>(task));}pool_->cond.notify_one();}private:struct Pool {std::mutex mtx;std::condition_variable cond;bool isClosed;std::queue<std::function<void()>> tasks;};std::shared_ptr<Pool> pool_;
};#endif //THREADPOOL_H

1,先看下 私有變量。

struct Pool {std::mutex mtx;std::condition_variable cond;bool isClosed;std::queue<std::function<void()>> tasks;};
std::shared_ptr<Pool> pool_;

一個結構體 Pool 將用到的變量,全部包含進去。

mtx 一個鎖,用于加入,取出任務。

cond 信號量,用于線程間同步。

isClosed 線程池退出的標志。

tasks 任務隊列,存放所有需要在線程中執行的任務。

pool_ 智能指針,管理所有資源。

2,構造函數

(1),默認開啟8個線程(size_t threadCount = 8),并在初始化列表中? 初始化pool_對象(std::make_shared<Pool>())

(2),循環啟動每個線程

for(){std::thread({//todo}).detach();
}

(3),加鎖? 確保 ,各個線程對 任務隊列(tasks) 不產生競爭,因為添加任務,取任務都要操作這個隊列。

std::unique_lock<std::mutex> locker(pool->mtx);

(4),單獨看一個線程。

首先判斷任務隊列是否為空,為空 則利用信號量阻塞當前線程。

else pool->cond.wait(locker);

如果線程池是退出狀態,則跳出當前循環,當前線程也會退出。

else if(pool->isClosed) break;

如果任務隊列不為空,則取出第一個任務,隊列減1,然后解鎖,執行任務,再加鎖。

auto task = std::move(pool->tasks.front());
pool->tasks.pop();
locker.unlock();
task();
locker.lock();

std::move 用于移動語義,允許在不復制內存的情況下轉移資源的所有權。這段代碼之后,相當于8個線程,從任務隊列tasks 中搶任務,搶到一個執行一個。比如A線程 搶到了任務1,任務1 在執行中過程中,由于隊列處于未加鎖狀態,那B線程,就可以繼續搶任務2。

3,添加任務

std::forward ,在一個函數中將參數以原始的形式傳遞給另一個函數,同時保持其值類別(lvalue 或 rvalue)和 const 修飾符。

這里將task 添加到 任務隊列?tasks中。并且利用locker 進行保護。這里添加完成之后,上述的8個線程就會從這個任務隊列中搶任務,然后執行。

    template<class F>void AddTask(F&& task) {{std::lock_guard<std::mutex> locker(pool_->mtx);pool_->tasks.emplace(std::forward<F>(task));}pool_->cond.notify_one();}

3,銷毀

將isClosed 標志置為false,并通知所有線程繼續執行,防止因為任務隊列為空,造成阻塞無法退出。在上述循環中,檢測到isClosed 為fasel,則while循環退出,線程退出。

    ~ThreadPool() {if(static_cast<bool>(pool_)) {{std::lock_guard<std::mutex> locker(pool_->mtx);pool_->isClosed = true;}pool_->cond.notify_all();}}

5,使用

構造完ThreadPool 之后,直接調用AddTask ,將任務傳入其中即可。

std::bind? 用于創建一個可調用對象,將其與特定的參數綁定在一起。

?在C++11 之下,封裝一個線程池 還是很優雅的。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/711499.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/711499.shtml
英文地址,請注明出處:http://en.pswp.cn/news/711499.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Windows系統搭建VisualSVN并結合內網穿透實現遠程訪問本地服務

文章目錄 前言1. VisualSVN安裝與配置2. VisualSVN Server管理界面配置3. 安裝cpolar內網穿透3.1 注冊賬號3.2 下載cpolar客戶端3.3 登錄cpolar web ui管理界面3.4 創建公網地址 4. 固定公網地址訪問 前言 SVN 是 subversion 的縮寫&#xff0c;是一個開放源代碼的版本控制系統…

js實現轉義、反轉義

兩種思路&#xff0c;一種是列出需要用到的轉義項&#xff0c;通過正則來轉化&#xff1b;另一種通過轉化為html語言&#xff0c;通過瀏覽器幫助我們翻譯&#xff0c;然后獲取innerText var HtmlUtil {/*1.用瀏覽器內部轉換器實現html編碼&#xff08;轉義&#xff09;*/html…

Spring 事務常見錯誤(上)

通過上一章的學習&#xff0c;我們了解了 Spring Data 操作數據庫的一些常見問題。這一章我們聊一聊數據庫操作中的一個非常重要的話題——事務管理。 Spring 事務管理包含兩種配置方式&#xff0c;第一種是使用 XML 進行模糊匹配&#xff0c;綁定事務管理&#xff1b;第二種是…

洗澡、泡腳真的能養生? 皮膚科醫生來科普

現如今人們越來越注重健康與養生&#xff0c;除了枸杞、生姜等食補外&#xff0c;各種保健方法和保健產品也層出不窮&#xff0c;還有泡腳、洗涼水澡等養生延緩衰老的方式也廣泛流行&#xff0c;那么泡腳與洗涼水澡真的有用嗎?西安國際醫學中心醫院皮膚科主任高鵬程特意進行了…

Timeplus-proton流處理器調研

概念 Timeplus是一個流處理器。它提供強大的端到端功能&#xff0c;利用開源流引擎Proton來幫助數據團隊快速直觀地處理流數據和歷史數據&#xff0c;可供各種規模和行業的組織使用。它使數據工程師和平臺工程師能夠使用 SQL 釋放流數據價值。 Timeplus 控制臺可以輕松連接到不…

K8S相關小技巧《一》

在實際使用Kubernetes的時候有一些常用的小技巧&#xff0c;在此分享給大家&#xff1a; 獲取用于拉取docker的密鑰的原本值&#xff0c;k8s docker registry pull secret decode&#xff1a; kubectl get secret/registry-pull-secret -n kube-iapply-qa -o json | jq .data…

女性三八節禮物攻略:她無法抗拒的五大禮物

隨著春風的溫柔拂面&#xff0c;我們即將迎來一年一度的三八國際婦女節。這個特別的日子&#xff0c;不僅是對女性貢獻的認可和慶祝&#xff0c;也是向我們生命中的女性表達感激和愛意的絕佳時機。在這個充滿溫馨和敬意的時刻&#xff0c;我們常常在思考&#xff0c;如何用一份…

信息學奧賽一本通1310:【例2.2】車廂重組

1310&#xff1a;【例2.2】車廂重組 時間限制: 1000 ms 內存限制: 65536 KB 提交數: 48051 通過數: 28919 【題目描述】 在一個舊式的火車站旁邊有一座橋&#xff0c;其橋面可以繞河中心的橋墩水平旋轉。一個車站的職工發現橋的長度最多能容納兩節車廂&#xff0c…

elementUI el-table中的對齊問題

用elementUI時&#xff0c;遇到了一個無法對齊的問題&#xff1a;代碼如下&#xff1a; <el-table :data"form.dataList" <el-table-column label"驗收結論" prop"checkResult" width"200"> <template slot-sco…

0005TS函數類型詳解

TypeScript 中的函數類型用于為函數定義參數類型和返回值類型。這提供了一個清晰的契約&#xff0c;指明函數應該如何被調用和期望返回什么類型的結果。以下是 TypeScript 中函數類型的一些基本用法和概念&#xff1a; 函數聲明 在 TypeScript 中&#xff0c;你可以為函數的參…

揭秘!Excel如何成為職場中的價值創造利器

文章目錄 一、Excel在生產力提升中的作用二、Excel在創造價值方面的應用案例三、Excel實用技巧分享四、Excel與其他工具的協同應用五、Excel學習的建議與展望《Excel函數與公式應用大全》亮點內容簡介作者簡介目錄 在當今信息爆炸的時代&#xff0c;數據處理和分析能力已成為職…

AI智能分析網關V4智慧商場方案,打造智慧化商業管理生態

AI智能視頻檢測技術在商場樓宇管理中的應用越來越廣泛。通過實時監控、自動識別異常事件和智能預警&#xff0c;這項技術為商場管理提供了更高效、更安全的保障。今天我們以TSINGSEE青犀視頻AI智能分析網關為例&#xff0c;給大家介紹一下AI視頻智能分析技術如何應用在商場樓宇…

搶單情況下的均衡分配機制

背景&#xff1a; 1、工單有多種類型。 2、客戶提交工單。 3、不同客服受理不同類型工單&#xff0c;受理工單類型存在交叉。 4、按照類型維度實現均衡分配。 方案&#xff1a; 1、為每種類型創建一個工單池&#xff0c;使用隊列&#xff0c;左進右出&#xff1b;客戶提交…

Android AIDL RemoteCallbackLIst

RemoteCallbackLIst 參考地址 RemoteCallbackList 是 Android SDK 中的一個類&#xff0c;用于幫助管理進程之間的回調。它專為進程間通信 (IPC) 場景而設計&#xff0c;在該場景中&#xff0c;應用程序的不同部分甚至不同的應用程序可能在不同的進程中運行。 以下是其關鍵功能…

將所有字母轉化為該字母后的第三個字母,即A->D,B->E

//編寫加密程序&#xff0c;規則&#xff1a;將所有字母轉化為該字母后的第三個字母&#xff0c;即A->D,B->E,C->F,…Y->B,Z->C //小寫字母同上&#xff0c;其他字符不做轉化。輸入&#xff1a;I love 007 輸出&#xff1a;L oryh 007 代碼&#xff1a; #inc…

GVA快速使用

1. clone 代碼&#xff0c; 使用goland打開Server目錄&#xff0c; 使用vsc打開前端web目錄&#xff0c;運行后端&#xff0c;前端 gin-vue-admin后臺管理系統 - 知乎 (zhihu.com) 2.了解端口配置 參考&#xff0c; 基于Go的后臺管理框架Gin-vue-admin_go vue admin-CSDN博客…

配置MMDetection的solov2攻略整理

目錄 一、MMDetection 特性 常見用法 二、ubuntu20.04配置solov2 三、Windows11配置solov2 一、MMDetection MMDetection是一個用于目標檢測的開源框架&#xff0c;由OpenMMLab開發和維護。它提供了豐富的預訓練模型和模塊&#xff0c;可以用于各種目標檢測任務&#xff…

kamacoder 11.共同祖先的C語言奇妙解法

11. 共同祖先 時間限制&#xff1a;1.000S 空間限制&#xff1a;32MB 題目描述 小明發現和小宇有共同祖先&#xff01;現在小明想知道小宇是他的長輩&#xff0c;晚輩&#xff0c;還是兄弟。 輸入描述 輸入包含多組測試數據。每組首先輸入一個整數N&#xff08;N<10&a…

redis的基本數據類型(一)

redis的基本數據類型 1、redis1.1、數據庫分類1.2、NoSQL分類1.3、redis簡介1.4、redis應用1.5、如何學習redis 2、redis的安裝2.1、Windows安裝2.2.1、客戶端redis管理工具 2.2、Linux安裝&#x1f525;2.2.1、redis核心文件2.2.2、啟動方式2.2.3、redis桌面客戶端1、redis命令…

定義類的成員比較函數,并在類的成員函數里面調用

定義一個自定義排序規則的成員函數&#xff0c;然后在類的成員函數中調用 文章目錄 1.聲明為static函數2.使用function3.使用匿名函數 1.聲明為static函數 #include <iostream> #include <algorithm> #include <list> class A { public:A(){std::list<i…