乙個簡單的c 執行緒池的封裝

2021-08-19 08:59:40 字數 4011 閱讀 3651

首先問三個問題:什麼是執行緒池?執行緒池的優勢是什麼?實現原理是什麼?

字面意思就是」乙個存放執行緒的池塘」,類似於記憶體池的概念,建立固定數量的執行緒,來處理多個任務,執行緒執行完乙個任務後不銷毀而是繼續執行下乙個任務,這樣就避免了執行緒的頻繁建立和銷毀,大大提高了效率(和多執行緒相模型相比),這也回答了第二個問題,執行緒池的優勢所在。

執行緒池不只有乙個執行緒組,還需要乙個任務佇列來方便執行緒池獲取任務,此任務隊列為被所有執行緒共享,因此在考慮類的資料結構是必須新增進來,另外,因為有多個執行緒共享乙個資源的情況(都會訪問任務佇列),還必須要考慮加鎖的問題。借用一張圖來說明執行緒池的工作流程:

首先是執行緒同步的類封裝condition.h:

#ifndef mythreadpool_condition_h

#define mythreadpool_condition_h

#include

//封裝乙個互斥量和條件變數作為狀態

typedef struct condition

condition_t;

class

condition_mutex

;#endif //mythreadpool_condition_h

具體實現condition.cpp:

#include "condition.h"

condition_mutex::condition_mutex()

condition_mutex::~condition_mutex()

//初始化

int condition_mutex::condition_init()

//加鎖

int condition_mutex::condition_lock()

//解鎖

int condition_mutex::condition_unlock()

//等待

int condition_mutex::condition_wait()

//固定時間等待

int condition_mutex::condition_timedwait(const

struct timespec *abstime)

//喚醒乙個睡眠執行緒

int condition_mutex::condition_signal()

//喚醒所有睡眠執行緒

int condition_mutex::condition_broadcast()

//釋放

int condition_mutex::condition_destroy()

接下來是執行緒池結構的封裝threadpool.h:

#ifndef mythreadpool_threadpool_h

#define mythreadpool_threadpool_h

//執行緒池標頭檔案

#include "condition.h"

//封裝執行緒池中的物件需要執行的任務物件

typedef struct task

task_t;

//下面是執行緒池結構體

typedef struct threadpool_data

threadpool_t;

class

threadpool

;#endif //mythreadpool_threadpool_h

執行緒池實現threadpool.cpp:

#include "threadpool.h"

#include

#include

#include

#include

#include

//建立的執行緒執行

static

void *thread_routine(void *arg)

}pool->idle--;

if(pool->first != null)

//退出執行緒池

if(pool->quit && pool->first == null)

pool->ready.condition_unlock();

break;

}//超時,跳出銷毀執行緒

if(timeout == 1)

pool->ready.condition_unlock();

}printf("thread %d is exiting\n", pthread_self());

return null;

}threadpool::threadpool(int threads)

threadpool::~threadpool()

//執行緒池初始化

void threadpool::threadpool_init(int threads)

//增加乙個任務到執行緒池

void threadpool::threadpool_add_task(void *(*run)(void *arg), void *arg)

else

workers.last = newtask; //佇列尾指向新加入的執行緒

//執行緒池中有執行緒空閒,喚醒

if(workers.idle > 0)

//當前執行緒池中線程個數沒有達到設定的最大值,建立乙個新的執行緒

else

if(workers.counter < workers.max_threads)

//結束,訪問

workers.ready.condition_unlock();

}//執行緒池銷毀

void threadpool::threadpool_destroy()

//加鎖

workers.ready.condition_lock();

//設定銷毀標記為1

workers.quit = 1;

//執行緒池中線程個數大於0

if(workers.counter > 0)

//正在執行任務的執行緒,等待他們結束任務

while(workers.counter)

}workers.ready.condition_unlock();

workers.ready.condition_destroy();

}

測試程式:

#include "threadpool.h"

#include

#include

#include

void* mytask1(void *arg)

void* mytask2(void *arg)

//測試**

int main(void)

int *arg = (int *)malloc(sizeof(int));

*arg = i;

if (i%2 == 0)

else

}return

0;}

執行結果分析:

在本測試程式中,主線程(即程序本身)連續建立了三個執行緒,6139904(暫記為1號執行緒),6676480(2號執行緒),7213056(3號執行緒),且不停地在向任務佇列中新增任務,從圖中看到,1號執行緒執行了任務0,2號執行緒執行了任務1,3號執行緒執行了任務2,由於奇數任務的執行時間較長(mytask2,休眠10秒鐘),1號執行緒和3號執行緒結束的比較快,又開始獲取新的任務,3號執行緒獲取任務3,進入長時間的休眠中,此時1號執行緒處理完任務4之後,繼續處理任務5,發現任務佇列已空,且輪詢等待2秒之後沒有獲取到新的任務,退出執行緒並銷毀。之後5號任務加入了佇列,執行緒池又重新建立了7213056(4號執行緒),……

從執行緒的執行時序可以看出,本執行緒池很好的完成了多工的執行緒分配,且執行沒有問題,封裝簡單易用。

參考原文:

乙個簡單的執行緒池

話說這個執行緒池也寫了好久了 做簡單的東西的時候也在用,最近因為乙個失誤刪掉了自己的一些檔案導致重新寫了一遍 所以貼出來,以防萬一 並且跟大佬們交流 created by cxhmyself on 18 4 10.include 都需要與互斥量一起才能工作 include include inclu...

乙個簡單的執行緒池

最近自己,很煩所以超級久沒學習了,今天趁著抗戰七十周年放三天假,趕緊看下書。廢話不多說。今天,介紹乙個簡單的執行緒池。首先說明什麼是執行緒池,執行緒池 是包含若干個執行緒,來處理多個任務的執行緒集合。它的目的是用來處理,大量的相對短暫的任務。這裡我們先來解釋下兩個概念,什麼叫大量呢?對於執行緒來說,...

封裝乙個簡單的池操作

臨界區同步類 class cmrthreadlock 析構函式 inline cmrthreadlock 功能函式 public 鎖定函式 virtual inline void lock 解鎖函式 virtual inline void unlock class cmrpoolobject cla...