線程池111

?

線程池框圖

C語言線程池詳解:從基礎到實現

通俗理解線程池

想象你開了一家快遞站,每天要處理很多包裹派送:

  1. ?沒有線程池?:每來一個包裹就雇一個新快遞員,送完就解雇
    • 問題:頻繁招聘解雇成本高(線程創建銷毀開銷大)
  2. ?有線程池?:固定雇傭5個快遞員,包裹來了就分配給空閑的快遞員
    • 優點:快遞員復用,效率高,管理方便

線程池就是這樣的"快遞員管理系統",預先創建一組線程,有任務時分配給空閑線程執行。

完整C語言線程池實現(帶詳細注釋)

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>#define THREAD_NUM 5  // 線程池中線程數量// 任務結構體(相當于快遞站的"包裹")
typedef struct {void (*function)(void *);  // 任務函數指針void *arg;                 // 函數參數
} Task;// 線程池結構體(相當于"快遞站")
typedef struct {Task *task_queue;          // 任務隊列(存放待處理的任務)int queue_capacity;        // 隊列容量int queue_size;            // 當前隊列中任務數量int queue_front;           // 隊首索引int queue_rear;            // 隊尾索引pthread_t *threads;        // 工作線程數組(相當于"快遞員")pthread_mutex_t mutex;    // 互斥鎖,保護任務隊列pthread_cond_t cond;       // 條件變量,線程等待信號int shutdown;              // 線程池關閉標志
} ThreadPool;// 創建線程池
ThreadPool* thread_pool_create(int capacity) {ThreadPool *pool = (ThreadPool *)malloc(sizeof(ThreadPool));// 初始化任務隊列pool->queue_capacity = capacity;pool->task_queue = (Task *)malloc(sizeof(Task) * capacity);pool->queue_size = 0;pool->queue_front = 0;pool->queue_rear = 0;// 初始化線程數組pool->threads = (pthread_t *)malloc(sizeof(pthread_t) * THREAD_NUM);// 初始化互斥鎖和條件變量pthread_mutex_init(&pool->mutex, NULL);pthread_cond_init(&pool->cond, NULL);// 設置線程池運行狀態pool->shutdown = 0;// 創建工作線程for (int i = 0; i < THREAD_NUM; i++) {pthread_create(&pool->threads[i], NULL, worker, (void *)pool);}return pool;
}// 工作線程函數(相當于"快遞員的工作流程")
void* worker(void* arg) {ThreadPool *pool = (ThreadPool *)arg;while (1) {pthread_mutex_lock(&pool->mutex);  // 加鎖保護任務隊列// 當任務隊列為空且線程池未關閉時,線程等待while (pool->queue_size == 0 && !pool->shutdown) {pthread_cond_wait(&pool->cond, &pool->mutex);  // 等待條件變量}// 如果線程池已關閉且任務已處理完,線程退出if (pool->shutdown && pool->queue_size == 0) {pthread_mutex_unlock(&pool->mutex);pthread_exit(NULL);}// 從任務隊列中取出一個任務Task task;task.function = pool->task_queue[pool->queue_front].function;task.arg = pool->task_queue[pool->queue_front].arg;// 更新隊列狀態pool->queue_front = (pool->queue_front + 1) % pool->queue_capacity;pool->queue_size--;pthread_mutex_unlock(&pool->mutex);  // 解鎖// 執行任務(快遞員開始派送包裹)printf("Thread %lu start working...\n", pthread_self());task.function(task.arg);  // 調用任務函數printf("Thread %lu finish work!\n", pthread_self());}return NULL;
}// 添加任務到線程池
void thread_pool_add(ThreadPool *pool, void (*func)(void *), void *arg) {pthread_mutex_lock(&pool->mutex);  // 加鎖保護任務隊列// 如果隊列已滿,等待(這里簡單處理,實際可以擴容或返回錯誤)while (pool->queue_size == pool->queue_capacity && !pool->shutdown) {pthread_cond_wait(&pool->cond, &pool->mutex);}if (pool->shutdown) {pthread_mutex_unlock(&pool->mutex);return;}// 添加任務到隊尾pool->task_queue[pool->queue_rear].function = func;pool->task_queue[pool->queue_rear].arg = arg;pool->queue_rear = (pool->queue_rear + 1) % pool->queue_capacity;pool->queue_size++;pthread_cond_signal(&pool->cond);  // 喚醒一個等待的線程pthread_mutex_unlock(&pool->mutex);  // 解鎖
}// 銷毀線程池
void thread_pool_destroy(ThreadPool *pool) {if (pool == NULL) return;// 設置關閉標志pool->shutdown = 1;// 喚醒所有等待的線程pthread_cond_broadcast(&pool->cond);// 等待所有線程退出for (int i = 0; i < THREAD_NUM; i++) {pthread_join(pool->threads[i], NULL);}// 釋放資源free(pool->threads);free(pool->task_queue);pthread_mutex_destroy(&pool->mutex);pthread_cond_destroy(&pool->cond);free(pool);
}// 示例任務函數1
void task_function1(void *arg) {int num = *(int *)arg;printf("Task1 processing number: %d\n", num);sleep(1);  // 模擬耗時操作
}// 示例任務函數2
void task_function2(void *arg) {char *str = (char *)arg;printf("Task2 processing string: %s\n", str);sleep(2);  // 模擬耗時操作
}int main() {// 創建線程池,任務隊列容量為10ThreadPool *pool = thread_pool_create(10);// 添加任務到線程池for (int i = 0; i < 10; i++) {int *num = (int *)malloc(sizeof(int));*num = i;thread_pool_add(pool, task_function1, (void *)num);}// 添加不同類型的任務char *str = "Hello ThreadPool";thread_pool_add(pool, task_function2, (void *)str);// 等待所有任務完成sleep(5);// 銷毀線程池thread_pool_destroy(pool);return 0;
}

關鍵組件詳細解釋

1. 任務隊列(Task Queue)

typedef struct {void (*function)(void *);  // 函數指針void *arg;                 // 函數參數
} Task;
  • ?作用?:存儲待執行的任務
  • ?原理?:使用環形隊列實現,避免頻繁內存分配
  • ?操作?:
    • 隊尾添加任務
    • 隊首取出任務

2. 線程池管理(ThreadPool)

typedef struct {Task *task_queue;         // 任務隊列int queue_capacity;       // 隊列容量int queue_size;           // 當前任務數// ...其他成員
} ThreadPool;
  • ?作用?:管理線程和任務隊列
  • ?關鍵成員?:
    • threads:工作線程數組
    • mutex:保護任務隊列的互斥鎖
    • cond:線程間通信的條件變量

3. 工作線程(Worker Thread)

void* worker(void* arg) {while (1) {// 1. 加鎖并檢查任務隊列// 2. 無任務時等待條件變量// 3. 取出任務并執行// 4. 解鎖}
}
  • ?工作流程?:
    1. 檢查任務隊列
    2. 無任務則等待
    3. 有任務則取出執行
    4. 循環處理

4. 任務添加(thread_pool_add)

void thread_pool_add(ThreadPool *pool, void (*func)(void *), void *arg) {// 1. 加鎖// 2. 檢查隊列狀態// 3. 添加任務到隊列// 4. 喚醒一個等待線程// 5. 解鎖
}
  • ?作用?:向線程池提交新任務
  • ?關鍵點?:
    • 隊列滿時等待
    • 添加后喚醒工作線程

5. 線程池銷毀(thread_pool_destroy)

void thread_pool_destroy(ThreadPool *pool) {// 1. 設置關閉標志// 2. 喚醒所有線程// 3. 等待線程退出// 4. 釋放資源
}
  • ?作用?:安全關閉線程池
  • ?關鍵點?:
    • 先通知所有線程
    • 等待線程自然退出

線程池工作流程圖

主線程:[創建線程池] → [添加任務] → [銷毀線程池]|               |↓               ↓
任務隊列: [任務1][任務2][任務3]...|↓
工作線程:[線程1取任務] → [執行] → [取下一個任務][線程2取任務] → [執行] → [取下一個任務]...

為什么需要這些機制?

  1. ?互斥鎖(mutex)??:

    • 防止多個線程同時訪問任務隊列導致數據混亂
  2. ?條件變量(cond)??:

    • 當任務隊列為空時,讓工作線程休眠等待
    • 當有新任務時喚醒線程,避免忙等待
  3. ?環形隊列?:

    • 高效利用內存,避免頻繁內存分配
    • 先進先出(FIFO)的任務處理順序
  4. ?線程復用?:

    • 避免頻繁創建銷毀線程的開銷
    • 控制并發數量,防止系統過載

實際應用場景

  1. ?網絡服務器?:處理大量客戶端請求
  2. ?文件處理?:批量處理大量文件
  3. ?數據計算?:并行計算任務
  4. ?GUI應用?:后臺耗時任務處理

擴展改進建議

  1. ?動態調整線程數?:根據負載自動增減線程
  2. ?任務優先級?:支持高優先級任務插隊
  3. ?任務取消?:支持取消已提交但未執行的任務
  4. ?超時機制?:設置任務執行超時時間
  5. ?任務結果獲取?:提供獲取任務執行結果的機制

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

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

相關文章

Qt-Advanced-Docking-System

直譯一下 &#xff1a; 先進的停靠系統 github: mfreiholz/Qt-Advanced-Docking-System: Advanced Docking System for Qt 這是這個項目的起源 這個最后一次更新&#xff1a; githubuser0xFFFF/Qt-Advanced-Docking-System: Advanced Docking System for Qt 這是另一個人復刻…

湖南(源點咨詢)市場調研 如何在行業研究中快速有效介入 中篇

我們接著起頭篇來說邁克爾波特認為一個行業內存在著五種基本競爭力量&#xff0c;即潛在入侵者、替代產品、供方、需方以及行業內現有競爭者。如附圖&#xff1a;即&#xff1a;同行業內現有競爭者的競爭能力、潛在競爭者進入的能力、替代品的替代能力、供應商的討價還價能力、…

【無標題】消息隊列(Message Queue)是一種**進程間通信(IPC)機制

消息隊列&#xff08;Message Queue&#xff09;是一種進程間通信&#xff08;IPC&#xff09;機制&#xff0c;它允許進程通過在隊列中添加和讀取消息來交換數據。與管道&#xff08;命名/匿名&#xff09;相比&#xff0c;消息隊列具有結構化消息、異步通信和消息持久化等特點…

mac中多版本JDK配置和切換

下載 從jdk官網下載即可&#xff0c;找到自己要用的版本。 官網&#xff1a;https://www.oracle.com/java/technologies/downloads/#jdk21-mac 我這里下載的jdk1.8和21。 根據自己芯片下載&#xff0c;一般都是m芯片。下載好后&#xff0c;點擊&#xff0c;一直下一步就行&…

【JVM】流程匯總

【JVM】流程匯總【一】編譯過程和內存分布【1】案例程序&#xff1a;簡單的 Java 類【2】Java 編譯過程&#xff1a;從.java到.class&#xff08;1&#xff09;編譯命令&#xff08;2&#xff09;編譯結果&#xff08;3&#xff09;字節碼的作用【3】Java 運行過程&#xff1a;…

專業MP3瘦身工具WinMP3Shrink 1.1,綠色單文件,極速壓縮

[軟件名稱]: 專業MP3瘦身工具WinMP3Shrink 1.1 [軟件大小]: 1.1 MB [軟件大小]: 夸克網盤 | 百度網盤 軟件介紹 WinMP3Shrink 是一款免費的 MP3 壓縮軟件&#xff0c;能夠有效減少 MP3 文件的體積&#xff0c;同時還能增強音質。即使不重新編碼&#xff0c;通過移除保留空間…

LeetCode 每日一題 2025/8/4-2025/8/10

記錄了初步解題思路 以及本地實現代碼&#xff1b;并不一定為最優 也希望大家能一起探討 一起進步 目錄8/4 904. 水果成籃8/5 3477. 水果成籃 II8/6 3479. 水果成籃 III8/7 3363. 最多可收集的水果數目8/8 808. 分湯8/9 231. 2 的冪8/10 869. 重新排序得到 2 的冪8/4 904. 水果…

Python爬蟲實戰:研究Ruia框架,構建博客園文章采集系統

1. 引言 1.1 研究背景與意義 在數字化時代,數據已成為驅動科技創新與產業升級的核心生產要素。互聯網作為全球最大的信息載體,蘊含著億級結構化、半結構化與非結構化數據,這些數據在商業決策、學術研究、公共服務等領域具有不可替代的價值。網絡爬蟲技術作為自動獲取網絡公…

Office安裝使用?借助Ohook開源工具?【圖文詳解】微軟Office產品

一、問題背景 很多用戶在使用 Office 軟件一段時間后&#xff0c;會遇到以下問題。 二、解決方案 Ohook 是 Office 獨有的可用方式&#xff0c;源自 GitHub 上的開源項目&#xff0c;代碼開源&#xff08;開源地址&#xff1a;https://github.com/asdcorp/ohook&#xff09;。 …

LeetCode簡單題 - 學習

力扣題庫 - 簡單題 - 僅記錄學習 來源地址&#xff1a; 力扣 (LeetCode) 全球極客摯愛的技術成長平臺 1. 兩數之和 給定一個整數數組 nums 和一個整數目標值 target&#xff0c;請你在該數組中找出 和為目標值 target 的那 兩個 整數&#xff0c;并返回它們的數組下標。 你…

Android Camera 打開和拍照APK源碼

完整下載路徑: 【免費】AndroidcameraAPK完整源碼(包括打開攝像頭和拍照保存功能)Android10驗證可完整運行資源-CSDN下載 效果: 源碼: package com.example.mycamera;import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appco…

【系統分析師】軟件需求工程——第11章學習筆記(上)

軟件需求工程是包括創建和維護軟件需求文檔所必需的一切活動的過程。可分為兩大工作&#xff1a;需求開發需求獲取需求分析需求定義&#xff08;編寫需求規格說明書&#xff09;需求驗證需求管理定義需求基線處理需求變更需求跟蹤在需求開發階段需要確定軟件所期望的用戶類型&a…

機器學習第七課之支持向量機SVM

目錄 簡介&#xff1a; 一、什么是支持向量機 二、如何選取最佳的超平面 1.超平面方程 (優化目標) 2.如何尋找最優的超平面 3.舉例分析 4.軟間隔?編輯 三、核函數 1舉例 2常用核函數 3.多項式核函數 4.高斯核函數: 四、svm的優缺點 五、支持向量機的API 六、案例…

P3232 [HNOI2013] 游走,solution

原題&#xff1a; link&#xff0c;點擊這里喵。 題意&#xff1a; 給定一個 nnn 個點 mmm 條邊的無向連通圖&#xff0c;圖無重邊和自環&#xff0c;頂點從 111 編號到 nnn&#xff0c;邊從 111 編號到 mmm。 小 Z 在該圖上進行隨機游走&#xff0c;初始時小 Z 在 111 號頂…

Docker容器部署discuz論壇與線上商城

準備 關閉防火墻&#xff0c;上下文[rootdocker ~]# systemctl disable --now firewalld[rootdocker ~]# setenforce 0下載應用yum remove runc -y ### rocky8才需要yum install -y yum-utils yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/cento…

Linux入門指南:26個基礎命令全解析

目錄 一.基礎概念與入門 1.Linux操作系統簡介 2.終端與shell的基本概念 3.命令行界面的優勢 二.基礎指令 1.whoami ?2.useradd/userdel/passwd ?3.pwd ?4.ls ?5.cd 6.touch 7.mkdir 8.tree 9.rmdir/rm 10.man 11.cp 12.mv 13.cat 14.le…

【后端】Java 8 特性 `User::getId` 語法(方法引用)介紹

文章目錄核心概念解析&#xff1a;方法引用的四種類型&#xff1a;關鍵特性&#xff1a;使用場景推薦&#xff1a;何時避免使用&#xff1a;性能說明&#xff1a;在 Java 中&#xff0c; User::getId 是一種稱為 方法引用&#xff08;Method Reference&#xff09; 的語法糖&a…

基于BP與CNN的圖像分類模型構建、超參數優化及性能對比研究?

一、實驗目的實驗目標構建基于神經網絡模型的數據分析與模式識別框架&#xff0c;探明神經網絡在大數據分析中的意義。實驗任務構建基于深度 BP 神經網絡與卷積神經網絡的數據分析與模式識別框架&#xff0c;將數據集 MNIST 與 CIFAR-10 分別在兩種模型中訓練&#xff0c;并比較…

HarmonyOS應用開發-低代碼開發登錄頁面(超詳細)

本篇文章我來手把手教大家做一個HarmonyOS 應用的登錄頁面&#xff0c;逐步講解&#xff0c;非常細致&#xff0c;百分百能學會&#xff0c;并提供全部源碼。頁面使用 DevEco Studio 的低代碼開發。 通過本文的實踐經驗&#xff0c;我想告訴大家&#xff0c; HarmonyOS 應用開發…

AJAX與axios框架

文章目錄前言案例跨域訪問總結?前言 提示&#xff1a;這里可以添加本文要記錄的大概內容&#xff1a; 通過 ajax 進行前后端交互 案例 此項目用到了javaweb知識 首先創建JavaWeb項目編寫代碼&#xff1a; package ajax;import java.io.IOException; import java.util.Arr…