Linux C++線程池實例

http://www.cnblogs.com/danxi/p/6636095.html

想做一個多線程服務器測試程序,因此參考了github的一些實例,然后自己動手寫了類似的代碼來加深理解。

目前了解的線程池實現有2種思路:

第一種:

主進程創建一定數量的線程,并將其全部掛起,此時線程狀態為idle,并將running態計數為0,等到任務可以執行了,就喚醒線程,此時線程狀態為running,計數增加,如果計數達到最大線程數,就再創建一組空閑線程,等待新任務,上一組線程執行完退出,如此交替。

第二種:

采用生成者-消費者模式,主進程作為生成者,創建FIFO隊列,在任務隊列尾部添加任務,線程池作為消費者在隊列頭部取走任務執行,這之間有人會提到無鎖環形隊列,在單生成者單消費者的模式下是有效的,但是線程池肯定是多消費者同時去隊列取任務,環形隊列會造成掛死。

我的實例采用第二種方式實現,在某些應用場景下,允許一定時間內,任務排隊的情況,重復利用已有線程會比較合適。

代碼比較占篇幅,因此折疊在下面。

?task.h:

復制代碼
 1 #ifndef TASK_H
 2 #define TASK_H
 3 
 4 #include <list>
 5 #include <pthread.h>
 6 
 7 using std::list;
 8 
 9 struct task {
10    void (*function) (void *);
11    void *arguments;
12    int id;
13 };
14 
15 struct work_queue {
16    work_queue(){
17         pthread_mutex_init(&queue_lock, NULL);
18         pthread_mutex_init(&queue_read_lock, NULL);
19         pthread_cond_init(&queue_read_cond, NULL);
20         qlen = 0;
21    }
22 
23    ~work_queue() {
24        queue.clear();
25        pthread_mutex_destroy(&queue_read_lock);
26        pthread_mutex_destroy(&queue_lock);
27        pthread_cond_destroy(&queue_read_cond);
28    }
29 
30    void push(task *tsk);
31    task *pull();
32    void post();
33    void wait();
34 
35 private:
36    int qlen;
37    list< task * > queue;
38    pthread_mutex_t queue_lock;
39    pthread_mutex_t queue_read_lock;
40    pthread_cond_t  queue_read_cond;
41 };
42 
43 #endif
復制代碼

?task.cpp

復制代碼
#include "task.h"void work_queue::push(task *tsk) {pthread_mutex_lock(&queue_lock);queue.push_back(tsk);qlen++;pthread_cond_signal(&queue_read_cond);pthread_mutex_unlock(&queue_lock);
}task* work_queue::pull() {wait();pthread_mutex_lock(&queue_lock);task* tsk = NULL;if (qlen > 0) {tsk = *(queue.begin());queue.pop_front();qlen--;if (qlen > 0)pthread_cond_signal(&queue_read_cond);}pthread_mutex_unlock(&queue_lock);return tsk;
}void work_queue::post() {pthread_mutex_lock(&queue_read_lock);pthread_cond_broadcast(&queue_read_cond);pthread_mutex_unlock(&queue_read_lock);
}void work_queue::wait() {pthread_mutex_lock(&queue_read_lock);pthread_cond_wait(&queue_read_cond, &queue_read_lock);pthread_mutex_unlock(&queue_read_lock);
}
復制代碼

threadpool.h

復制代碼
 1 #ifndef THREAD_POOL_H
 2 #define THREAD_POOL_H
 3 
 4 #include "task.h"
 5 #include <vector>
 6 
 7 using std::vector;
 8 
 9 #define safe_delete(p)  if (p) { delete p;  p = NULL; }
10 
11 struct threadpool {
12     threadpool(int size) : pool_size(size)
13                          , thread_list(size, pthread_t(0))
14                          , queue(NULL)
15                          , finish(false)
16                          , ready(0) {
17 
18         pthread_mutex_init(&pool_lock, NULL);
19     }
20 
21     ~threadpool() {
22         thread_list.clear();
23         safe_delete(queue);
24         pthread_mutex_destroy(&pool_lock);
25     }
26 
27     void init();
28     void destroy();
29     static void* thread_run(void *tp);
30 
31     void incr_ready();
32     void decr_ready();
33     bool close() const;
34     
35     work_queue *queue;
36     
37 private:
38     int pool_size;
39     int ready;
40     bool finish;
41     pthread_mutex_t pool_lock;
42     vector <pthread_t> thread_list;
43 };
44 
45 
46 #endif
復制代碼

threadpool.cpp

復制代碼
 1 /*
 2  * threadpool.cpp
 3  *
 4  *  Created on: 2017年3月27日
 5  *      Author: Administrator
 6  */
 7 
 8 #include "threadpool.h"
 9 
10 
11 void* threadpool::thread_run(void *tp) {
12     threadpool *pool = (threadpool *) tp;
13     pool->incr_ready();
14 
15     while(1) {
16         task* tsk = pool->queue->pull();
17         if (tsk) {
18             (tsk->function)(tsk->arguments);
19             delete tsk;
20             tsk = NULL;
21         }
22 
23         if (pool->close())
24             break;
25     }
26 
27     pool->decr_ready();
28 
29     return NULL;
30 }
31 
32 void threadpool::incr_ready() {
33     pthread_mutex_lock(&pool_lock);
34     ready++;
35     pthread_mutex_unlock(&pool_lock);
36 }
37 
38 void threadpool::decr_ready() {
39     pthread_mutex_lock(&pool_lock);
40     ready--;
41     pthread_mutex_unlock(&pool_lock);
42 }
43 
44 bool threadpool::close() const {
45     return finish;
46 }
47 
48 void threadpool::init() {
49     queue = new work_queue;
50     if (!queue) {
51         return;
52     }
53 
54     for(int i; i<pool_size; i++) {
55         pthread_create(&thread_list[i], NULL, threadpool::thread_run, (void *)this);
56     }
57 
58     while(ready != pool_size) {}
59 }
60 
61 void threadpool::destroy() {
62     finish = true;
63 
64     while(ready) {
65         if(queue) {
66             queue->post();
67         }
68     }
69 }
復制代碼

main.cpp

復制代碼
 1 //============================================================================
 2 // Name        : thread_pool.cpp
 3 // Author      : dancy
 4 // Version     :
 5 // Copyright   : Your copyright notice
 6 // Description : Hello World in C++, Ansi-style
 7 //============================================================================
 8 
 9 #include <iostream>
10 #include "threadpool.h"
11 #include <pthread.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 
15 using namespace std;
16 
17 void job(void *tsk){
18     printf("job %-2d working on Thread #%u\n", ((task *)tsk)->id, (int)pthread_self());
19 }
20 
21 task *make_task(void (*func) (void *), int id) {
22     task *tsk = new task;
23     if (!tsk)
24         return NULL;
25     
26     tsk->function = func;
27     tsk->arguments = (void *)tsk;
28     tsk->id = id;
29     
30     return tsk;
31 }
32 
33 int main() {
34     threadpool tp(4);
35     tp.init();
36 
37     for(int i=0; i<40; i++) 
38         tp.queue->push(make_task(&job, i+1));
39     
40     tp.destroy();
41     printf("all task has completed\n");
42     return 0;
43 }
復制代碼

?

以上代碼需要在linux下編譯,mingw下封裝的pthread_t,多了一個void *指針,如果要適配還需要自己再封裝一次。



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

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

相關文章

Java編寫簡單的自定義異常類

除了系統中自己帶的異常&#xff0c;我們也可以自己寫一些簡單的異常類來幫助我們處理問題。 所有的異常命名都是以Exception結尾&#xff0c;并且都是Exception的子類。 假設我們要編寫一個人類的類&#xff0c;為了判斷年齡的輸入是否合法&#xff0c;我們編寫了一個名為Il…

shared_ptr簡介以及常見問題

http://blog.csdn.net/stelalala/article/details/19993425 本文中的shared_ptr以vs2010中的std::tr1::shared_ptr作為研究對象。可能和boost中的有些許差異&#xff0c;特此說明。 基本功能 shared_ptr提供了一個管理內存的簡單有效的方法。shared_ptr能在以下方面給開發提供便…

【Java學習筆記九】多線程

程序&#xff1a;計算機指令的集合&#xff0c;它以文件的形式存儲在磁盤上&#xff0c;是應用程序執行的藍本。 進程&#xff1a;是一個程序在其自身的地址空間中的一次執行活動。進程是資源申請、調度和獨立運行的單位&#xff0c;因此&#xff0c;它使用系統中的運行資源。而…

【C++11新特性】 C++11智能指針之weak_ptr

http://blog.csdn.net/xiejingfa/article/details/50772571 原創作品&#xff0c;轉載請標明&#xff1a;http://blog.csdn.net/Xiejingfa/article/details/50772571 如題&#xff0c;我們今天要講的是C11引入的三種智能指針中的最后一個&#xff1a;weak_ptr。在學習weak_ptr之…

【C++學習筆記四】運算符重載

當調用一個重載函數和重載運算符時&#xff0c;編譯器通過把您所使用的參數類型和定義中的參數類型相比較&#xff0c;巨鼎選用最合適的定義。&#xff08;重載決策&#xff09; 重載運算符時帶有特殊名稱的函數&#xff0c;函數名是由關鍵字operator和其后要重載的運算符符號…

【C++11新特性】 C++11智能指針之unique_ptr

原創作品&#xff0c;轉載請標明&#xff1a;http://blog.csdn.net/Xiejingfa/article/details/50759210 在前面一篇文章中&#xff0c;我們了解了C11中引入的智能指針之一shared_ptr&#xff0c;今天&#xff0c;我們來介紹一下另一種智能指針unique_ptr。 unique_ptr介紹 uni…

C++派生類對象和基類對象賦值

在C中&#xff0c;我們允許 將派生類對象賦給基類對象。&#xff08;不允許將基類對象賦給派生類對象&#xff09; 只會將基類對象成員賦值用基類指針指向派生類對象。&#xff08;不允許用派生類指針指向基類對象&#xff09; 基類指針只能操作基類中的成員基類引用作為派生類…

【C++11新特性】 C++11智能指針之shared_ptr

http://blog.csdn.net/Xiejingfa/article/details/50750037 原創作品&#xff0c;轉載請標明&#xff1a;http://blog.csdn.net/Xiejingfa/article/details/50750037 C中的智能指針首先出現在“準”標準庫boost中。隨著使用的人越來越多&#xff0c;為了讓開發人員更方便、更安…

C++(純)虛函數重寫時訪問權限更改問題

我們知道在Java中是自動實現多態的&#xff0c;Java中規定重寫的方法的訪問權限不能縮小。那么在C中我們實現多態的時候是否可以更改&#xff08;縮小&#xff09;訪問權限呢&#xff1f; 經過測試&#xff0c;得到的答案如下&#xff1a;如果用基類指針指向派生類對象實現多態…

C++ — 智能指針的簡單實現以及循環引用問題

http://blog.csdn.net/dawn_sf/article/details/70168930 智能指針 ____________________________________________________ 今天我們來看一個高大上的東西&#xff0c;它叫智能指針。 哇這個名字聽起來都智能的不得了&#xff0c;其實等你了解它你一定會有一點失望的。。。。因…

C++(靜態)(常量)數據進行初始化問題以及靜態變量析構

在C11標準以前我們都不可以在類中對數據成員初始化&#xff0c;僅能在構造函數中進行初始化&#xff1a; class A {int a,b; double c; string d;A():a(1),b(2),c(3),d(""){} };在C11標準以后我們可以在類中對非靜態成員進行初始化。實際上的機制是在調用構造函數的…

C++this指針的用法

參考博客&#xff1a;https://www.cnblogs.com/zhengfa-af/p/8082959.html 在 訪問對象的非靜態成員時會隱式傳遞一個參數&#xff0c;即對象本身的指針&#xff0c;這個指針名為this。 例如&#xff1a; class A {int a1;public:A(){}void GetA(int a){cout<<this-&g…

C++開發者都應該使用的10個C++11特性

http://blog.jobbole.com/44015/ 感謝馮上&#xff08;治不好你我就不是獸醫 &#xff09;的熱心翻譯。如果其他朋友也有不錯的原創或譯文&#xff0c;可以嘗試推薦給伯樂在線。】 在C11新標準中&#xff0c;語言本身和標準庫都增加了很多新內容&#xff0c;本文只涉及了一些皮…

C++不能被聲明為虛函數

虛函數是為了實現多態&#xff0c;但是顯然并不是所有函數都可以聲明為虛函數的。 不能被聲明為虛函數的函數有兩類&#xff1a; 不能被繼承的函數不能被重寫的函數 因此&#xff0c;這些函數都不能被聲明為虛函數 普通函數構造函數 如果構造函數定義為虛函數&#xff0c;則…

類的聲明與定義

類的前向聲明&#xff1a; class A;在聲明之后&#xff0c;定義之前&#xff0c;類A是一個不完全類型&#xff0c;即知道A是一個類&#xff0c;但是不知道包含哪些成員。不完全類型只能以有限方式使用&#xff0c;不能定義該類型的對象&#xff0c;不完全類型只能用于定義指向…

shared_ptr的一些尷尬

http://blog.csdn.net/henan_lujun/article/details/8984543 shared_ptr在boost庫中已經有多年了&#xff0c;C11又為其正名&#xff0c;把他引入了STL庫&#xff0c;放到了std的下面&#xff0c;可見其頗有用武之地&#xff1b;但是shared_ptr是萬能的嗎&#xff1f;有沒有什…

C++轉換構造函數和類型轉換函數

參考博客&#xff1a;https://blog.csdn.net/feiyanaffection/article/details/79183340 隱式類型轉換 如果不同類型的數據在一起操作的時候編譯器會自動進行一個數據類型轉換。例如常用的基本數據類型有如下類型轉換關系&#xff1a; 轉換構造函數 構造函數有且僅有一個參數…

C++總結8——shared_ptr和weak_ptr智能指針

http://blog.csdn.net/wendy_keeping/article/details/75268687 智能指針的提出&#xff1a;智能指針是存儲指向動態分配對象指針的類&#xff0c;用于生存期控制。能夠確保正確銷毀動態分配的內存&#xff0c;防止內存泄露。 1.智能指針的分類&#xff1a; 不帶引用計數的智能…

C++析構函數執行順序

今天發現主程序中有多個對象時析構函數的執行順序不是對象定義的順序&#xff0c;而是對象定義順序反過來。 思考了一下&#xff0c;結合之前繼承、成員對象等的析構函數執行的順序&#xff0c;我覺得析構函數執行的順序為&#xff1a;構造函數的順序反過來&#xff0c;可能是…

c++寫時拷貝1

http://blog.csdn.net/SuLiJuan66/article/details/48882303 Copy On Write Copy On Write(寫時復制)使用了“引用計數”&#xff08;reference counting&#xff09;&#xff0c;會有一個變量用于保存引用的數量。當第一個類構造時&#xff0c;string的構造函數會根據傳入的參…