【池式組件】線程池的原理與實現

線程池的原理與實現

  • 線程池簡介
    • 1.線程池
    • 1.線程池
    • 2.數量固定的原因
    • 3.線程數量如何確定
    • 4.為什么需要線程池
    • 5.線程池結構
  • 線程池的實現
    • 數據結構設計
      • 1.任務結構
      • 2.任務隊列結構
      • 3.線程池結構
    • 接口設計
  • 線程池的應用
    • reactor
    • redis 中線程池
    • skynet 中線程池

線程池簡介

1.線程池

1.線程池

一種管理維持固定線程數量的池式結構。

2.數量固定的原因

  • 避免頻繁的創建和銷毀線程,造成資源浪費
  • 隨著線程的數量不斷增多,并不能實現性能的提升,相反可能造成系統負擔

3.線程數量如何確定

  • CPU密集型:proc(CPU核心數)
  • IO密集型(網絡IO,磁盤IO):2 * proc(CPU核心數)

4.為什么需要線程池

某類任務執行特別耗時,造成阻塞,嚴重影響該線程執行其他任務
作用:

  • 復用線程資源;
  • 減少線程創建和銷毀的開銷;
  • 可異步處理生產者線程的任務;
  • 減少了多個任務(不是一個任務)的執行時間;

5.線程池結構

線程池屬于一種生產消費模型。
線程池運行環境構成:
生產者線程:發布任務
隊列:存儲任務,調度線程池
消費者線程:取出任務,執行任務

線程池的實現

數據結構設計

1.任務結構

typedef struct task_s {void *next;handler_pt func;void *arg;
} task_t;

2.任務隊列結構

typedef struct task_queue_s {void *head;void **tail; int block;spinlock_t lock;pthread_mutex_t mutex;pthread_cond_t cond;
} task_queue_t;

3.線程池結構

struct thrdpool_s {task_queue_t *task_queue;atomic_int quit;int thrd_count;pthread_t *threads;
};

接口設計


// 創建對象的時候,回滾式的
static task_queue_t *
__taskqueue_create() {task_queue_t *queue = (task_queue_t *)malloc(sizeof(*queue));if (!queue) return NULL;int ret;ret = pthread_mutex_init(&queue->mutex, NULL);if (ret == 0) {ret = pthread_cond_init(&queue->cond, NULL);if (ret == 0) {spinlock_init(&queue->lock);queue->head = NULL;queue->tail = &queue->head;queue->block = 1;return queue;}pthread_cond_destroy(&queue->cond);}pthread_mutex_destroy(&queue->mutex);return NULL;
}static void
__nonblock(task_queue_t *queue) {pthread_mutex_lock(&queue->mutex);queue->block = 0;pthread_mutex_unlock(&queue->mutex);pthread_cond_broadcast(&queue->cond);
}static inline void 
__add_task(task_queue_t *queue, void *task) {void **link = (void **)task; // malloc *link = NULL; // task->next = NULL;spinlock_lock(&queue->lock);*queue->tail = link;queue->tail = link;spinlock_unlock(&queue->lock);pthread_cond_signal(&queue->cond);
}static inline void * 
__pop_task(task_queue_t *queue) {spinlock_lock(&queue->lock);if (queue->head == NULL) {spinlock_unlock(&queue->lock);return NULL;}task_t *task;task = queue->head;queue->head = task->next;if (queue->head == NULL) {queue->tail = &queue->head;}spinlock_unlock(&queue->lock);return task;
}static inline void * 
__get_task(task_queue_t *queue) {task_t *task;// 虛假喚醒while ((task = __pop_task(queue)) == NULL) {pthread_mutex_lock(&queue->mutex);if (queue->block == 0) {// break;pthread_mutex_unlock(&queue->mutex);return NULL;}// 1. 先 unlock(&mtx);// 2. 在 cond 休眠// ----- 生產者產生任務  signal// 3. 在 cond 喚醒// 4. 加上  lock(&mtx);pthread_cond_wait(&queue->cond, &queue->mutex);pthread_mutex_unlock(&queue->mutex);}return task;
}static void
__taskqueue_destroy(task_queue_t *queue) {task_t *task;while ((task = __pop_task(queue))) { // 任務的生命周期由 thrdpool 管理free(task);}spinlock_destroy(&queue->lock);pthread_cond_destroy(&queue->cond);pthread_mutex_destroy(&queue->mutex);free(queue);
}static void *
__thrdpool_worker(void *arg) {thrdpool_t *pool = (thrdpool_t*) arg;task_t *task;void *ctx;while (atomic_load(&pool->quit) == 0) {task = (task_t*)__get_task(pool->task_queue);if (!task) break;handler_pt func = task->func;ctx = task->arg;free(task);func(ctx);}return NULL;
}static void 
__threads_terminate(thrdpool_t * pool) {atomic_store(&pool->quit, 1);__nonblock(pool->task_queue);int i;for (i=0; i<pool->thrd_count; i++) {pthread_join(pool->threads[i], NULL);}
}static int 
__threads_create(thrdpool_t *pool, size_t thrd_count) {pthread_attr_t attr;int ret;ret = pthread_attr_init(&attr);if (ret == 0) {pool->threads = (pthread_t *)malloc(sizeof(pthread_t) * thrd_count);if (pool->threads) {int i = 0;for (; i < thrd_count; i++) {if (pthread_create(&pool->threads[i], &attr, __thrdpool_worker, pool) != 0) {break;}}pool->thrd_count = i;pthread_attr_destroy(&attr);if (i == thrd_count)return 0;__threads_terminate(pool);free(pool->threads);}ret = -1;}return ret;
}void
thrdpool_terminate(thrdpool_t * pool) {atomic_store(&pool->quit, 1);__nonblock(pool->task_queue);
}thrdpool_t *
thrdpool_create(int thrd_count) {thrdpool_t *pool;pool = (thrdpool_t*) malloc(sizeof(*pool));if (!pool) return NULL;task_queue_t *queue = __taskqueue_create();if (queue) {pool->task_queue = queue;atomic_init(&pool->quit, 0);if (__threads_create(pool, thrd_count) == 0) {return pool;}__taskqueue_destroy(pool->task_queue);}free(pool);return NULL;
}int
thrdpool_post(thrdpool_t *pool, handler_pt func, void *arg) {if (atomic_load(&pool->quit) == 1) {return -1;}task_t *task = (task_t *)malloc(sizeof(task_t));if (!task) return -1;task->func = func;task->arg = arg;__add_task(pool->task_queue, task);return 0;
}void
thrdpool_waitdone(thrdpool_t *pool) {int i;for (i=0; i<pool->thrd_count; i++) {pthread_join(pool->threads[i], NULL);}__taskqueue_destroy(pool->task_queue);free(pool->threads);free(pool);
}

線程池的應用

reactor

在這里插入圖片描述
在一個事件循環中,可以處理多個就緒事件,這些就緒事件在reactor 模型中時串行執行的,一個事件處理若耗時較長,會延遲其他同時觸發的事件的處理(對于客戶端而言,響應會變得較慢)。

redis 中線程池

在這里插入圖片描述
作用:讀寫 io 處理以及數據包解析、壓縮;

skynet 中線程池

在這里插入圖片描述

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

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

相關文章

第7課 SQL入門之創建計算字段

文章目錄 7.1 計算字段7.2 拼接字段使用別名 7.3 執行算術計算 這一課介紹什么是計算字段&#xff0c;如何創建計算字段&#xff0c;以及如何從應用程序中使用別名引用它們。 7.1 計算字段 存儲在數據庫表中的數據一般不是應用程序所需要的格式&#xff0c;下面舉幾個例子。 …

前端Excel導出實用方案(完整源碼,可直接應用)

目錄 前言&#xff1a; 技術選型&#xff1a; 主要功能點&#xff1a; 核心代碼&#xff1a; 完整代碼&#xff1a; 開發文檔 前言&#xff1a; 在前后端分離開發為主流的時代&#xff0c;很多時候&#xff0c;excel導出已不再由后端主導&#xff0c;而是把導出的操作移…

關于鎖的粒度問題——面試

鎖的粒度劃分主要有三種&#xff1a;表級鎖、頁級鎖和行鎖 1.表級鎖&#xff1a; 對整張表加鎖&#xff0c;粒度最大&#xff0c;加鎖的并發度最低&#xff0c;會導致其他事務無法訪問該表&#xff0c;只有當前事務提交或者回滾后才能釋放鎖。表級鎖適用于對表進行全表操作的場…

DeepIn,UOS統信專業版安裝運行Java,JavaFx程序

因為要適配國產統信UOS系統&#xff0c;要求JavaFx程序能簡便雙擊運行&#xff0c;由于網上UOS開發相關文章少&#xff0c;多數文章沒用&#xff0c;因此花了不少時間&#xff0c;踩了不少坑&#xff0c;下面記錄一些遇到的問題&#xff0c;我的程序環境是jdk1.8&#xff0c;為…

【K8s】Kubernetes CRD 介紹(控制器)

文章目錄 CRD 概述1. 操作CRD1.1 創建 CRD1.2 操作 CRD 2. 其他筆記2.1 Kubectl 發現機制2.2 校驗 CR2.3 簡稱和屬性 3. 架構設計3.1 控制器概覽 參考 CRD 概述 CR&#xff08;Custom Resource&#xff09;其實就是在 Kubernetes 中定義一個自己的資源類型&#xff0c;是一個具…

如何為 3D 模型制作紋理的最佳方法

在線工具推薦&#xff1a; 3D數字孿生場景編輯器 - GLTF/GLB材質紋理編輯器 - 3D模型在線轉換 - Three.js AI自動紋理開發包 - YOLO 虛幻合成數據生成器 - 三維模型預覽圖生成器 - 3D模型語義搜索引擎 您可以通過不同的方式為 3D 模型創建 3D 紋理。下面我們將介紹為 3D …

《opencv實用探索·十四》VideoCapture播放視頻和視像頭調用

1、VideoCapture播放視頻 #include <opencv2/opencv.hpp> #include <iostream>using namespace std; using namespace cv;int main() {// 定義相關VideoCapture對象VideoCapture capture;// 打開視頻文件capture.open("1.avi");// 判斷視頻流讀取是否正…

Python os模塊及用法

os 模塊代表了程序所在的操作系統&#xff0c;主要用于獲取程序運行所在操作系統的相關信息。 在 Python 的交互式解釋器中先導入 os 模塊&#xff0c;然后輸入 os.__all__ 命令&#xff08;__all__ 變量代表了該模塊開放的公開接口&#xff09;&#xff0c;即可看到該模塊所包…

Linux DataEase數據可視化分析工具本地部署與遠程訪問

文章目錄 前言1. 安裝DataEase2. 本地訪問測試3. 安裝 cpolar內網穿透軟件4. 配置DataEase公網訪問地址5. 公網遠程訪問Data Ease6. 固定Data Ease公網地址 前言 DataEase 是開源的數據可視化分析工具&#xff0c;幫助用戶快速分析數據并洞察業務趨勢&#xff0c;從而實現業務…

ExecutorService介紹

參考&#xff1a;https://blog.csdn.net/fwt336/article/details/81530581 前言 在開發中為了提高系統的響應速度和處理能力會使用到多線程&#xff0c;但線程的創建和釋放&#xff0c;需要占用不小的內存和資源。如果每次需要使用線程時&#xff0c;都new 一個Thread的話&…

【LeetCode】2723. 兩個 Promise 對象相加

兩個 Promise 對象相加 題目題解 題目 給定兩個 promise 對象 promise1 和 promise2&#xff0c;返回一個新的 promise。promise1 和 promise2 都會被解析為一個數字。返回的 Promise 應該解析為這兩個數字的和。 示例 1&#xff1a; 輸入&#xff1a; promise1 new Promise…

geoserver根據屬性字段值設置不同的顏色

<?xml version"1.0" encoding"UTF-8"?> <StyledLayerDescriptor xmlns"http://www.opengis.net/sld" xmlns:xlink"http://www.w3.org/1999/xlink" xmlns:ogc"http://www.opengis.net/ogc" xmlns:xsi"http:/…

中國聚羥基脂肪酸酯(PHA)市場評估與投資戰略報告(2024版)

內容簡介&#xff1a; PHA英文名稱為 Polyhydroxyalkanoates&#xff0c;是近20多年迅速發展起來的&#xff0c;很多天然原料合成的一種聚酯。PHA是生物基生物降解材料&#xff0c;具有良好的生物相容性和可加工性。防止水汽的穿透是保鮮包裝中的重要指標&#xff0c;PHA 有良…

os.walk()遍歷文件夾/文件

天行健&#xff0c;君子以自強不息&#xff1b;地勢坤&#xff0c;君子以厚德載物。 每個人都有惰性&#xff0c;但不斷學習是好好生活的根本&#xff0c;共勉&#xff01; 文章均為學習整理筆記&#xff0c;分享記錄為主&#xff0c;如有錯誤請指正&#xff0c;共同學習進步。…

P3 Qt 控件 —— pushButton

前言 &#x1f3ac; 個人主頁&#xff1a;ChenPi &#x1f43b;推薦專欄1: 《C_ChenPi的博客-CSDN博客》??? &#x1f525; 推薦專欄2: 《Linux C應用編程&#xff08;概念類&#xff09;_ChenPi的博客-CSDN博客》??? &#x1f33a;本篇簡介 &#xff1a;這一章我們學一…

Python evalml 庫:自動化機器學習的新前景

更多資料獲取 &#x1f4da; 個人網站&#xff1a;ipengtao.com 在機器學習領域&#xff0c;evalml 庫嶄露頭角&#xff0c;為開發者提供了一個強大而高效的自動化機器學習框架。本文將深入介紹 evalml 的核心功能、使用方法以及在實際項目中的應用。通過詳實的示例代碼&#…

前端高頻面試題大全-面試必看

內容較多&#xff0c;建議查看目錄&#xff0c;方便食用 高頻 React和Vue的區別 通常解法&#xff1a;vue是采用指令結合vue-loader實現構件用戶界面的漸進式框架&#xff0c;React是采用JSX構件用戶界面的組件化開發 詳細解法&#xff1a;在渲染界面的時候DOM操作是昂貴的&…

【Linux系統編程】項目自動化構建工具make/Makefile

介紹&#xff1a; make和Makefile是用于編譯和構建C/C程序的工具和文件。Makefile是一個文本文件&#xff0c;其中包含了編譯和構建程序所需的規則和指令。它告訴make工具如何根據源代碼文件生成可執行文件&#xff0c;里面保存的是依賴關系和依賴方法。make是一個命令行工具&a…

智匯恒星科技|控樂屋.全宅智能冠軍代言來啦, 智慧家居千億藍海

隨著5G、大數據、云計算、物聯網等技術的發展&#xff0c;智能化正覆蓋人們生活的方方面面&#xff0c;全屋智能的出現為“一鍵式”智能家居生活享受提供無限可能。近年來智能家居行業總體規模增長迅速&#xff0c;數據顯示&#xff0c;2022年中國智能家居行業市場規模約為6200…

Java內部類

文章目錄 什么是 Java 中的內部類&#xff1f;有哪些類型的內部類&#xff1f;匿名內部類局部內部類&#xff08;定義在方法中的類&#xff09;局部內部類靜態內部類 Java 類中不僅可以定義變量和方法&#xff0c;還可以定義類&#xff0c;這樣定義在類內部的類就被稱為內部類。…