程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 在Linux下寫一個線程池以及線程池的一些用法和注意點,linux線程

在Linux下寫一個線程池以及線程池的一些用法和注意點,linux線程

編輯:關於C語言

在Linux下寫一個線程池以及線程池的一些用法和注意點,linux線程


-->線程池介紹(大部分來自網絡)

   在這個部分,詳細的介紹一下線程池的作用以及它的技術背景以及他提供的一些服務等。大部分內容來自我日常生活中在網絡中學習到的一些概念性的東西。

-->代碼(大約240行)

   測試一下,具體的實現。

-->代碼下載

--------------------------------------------------------------------------------------------------------------------------------------

-->線程池介紹

1、技術背景:服務器程序利用線程技術響應客戶請求已經司空見慣,但是線程的使用是有待優化和處理的。單線程執行並不是一個高效的方式,這個時候可能就要考慮高並發,多線程等方式。線程池也是線程優化的一種方式。

在面向對象的過程中,對象的創建和銷毀是非常占資源的,每創建一個對象都要獲取內存資源以及其他一些資源。在Java中更是如此,他要跟蹤每一個對象,在它使用完畢的時候,自動的銷毀它並垃圾回收。可想而知,運行的速度之慢。這就產生了“池化技術”。

2、線程池如何提高服務器程序的性能?

     ●T1 = 創建線程

   ●T2 = 執行線程 包括訪問共享數據、線程同步等

   ●T3 = 銷毀線程

   ●T = T1 + T2 + T3   

  單線程的情況下,系統花大量的時間再T1、T3階段。我們要采取最優的措施,減少T1和T3的系統開銷。線程池不僅調整T1,T3產生的時間段,而且它還顯著減少了創建線程的數目。

假設:一台服務器,每天要處理10萬個請求,這時候,我們比較不用線程池的技術和用線程池,他們的區別。
如果沒有用線程池的話,那麼程序將會用大把的時候來創建這10萬個線程,用線程池,我們一般可用的線程數不會大於10萬,所以可以大大減小開銷。

3、具體工作流程

    線程池是一種多線程處理形式,處理過程中將任務添加到隊列,然後在創建線程後自動啟動這些任務。線程池線程都是後台線程。每個線程都使用默認的堆棧大小,以默認的優先級運行,並處於多線程單元中。如果某個線程在托管代碼中空閒(如正在等待某個事件),則線程池將插入另一個輔助線程來使所有處理器保持繁忙。如果所有線程池線程都始終保持繁忙,但隊列中包含掛起的工作,則線程池將在一段時間後創建另一個輔助線程但線程的數目永遠不會超過最大值。超過最大值的線程可以排隊,但他們要等到其他線程完成後才啟動。

4、何時不使用線程池線程  

    ● 如果需要使一個任務具有特定優先級

    ● 如果具有可能會長時間運行(並因此阻塞其他任務)的任務

    ● 如果需要將線程放置到單線程單元中(線程池中的線程均處於多線程單元中)

    ● 如果需要永久標識來標識和控制線程,比如想使用專用線程來終止該線程,將其掛起或按名稱發現它

5、一般使用線程池的程序的特點

    ● 需要花費大量的時候,並且請求的時間比較短。

    ● 對性能要求苛刻的應用,比如要求服務器迅速響應客戶請求。

    ● 接受突發性的大量請求,但不至於使服務器因此產生大量線程的應用。

 

-->代碼

     為了方便貼出代碼,我全部放在一個文件裡。運行gcc main.c -o main -lpthread -lrt運行  

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <unistd.h>
  4 #include <string.h>
  5 #include <errno.h>
  6 #include <time.h>
  7 #include <pthread.h>
  8 
  9 typedef struct condition
 10 {
 11     pthread_mutex_t pmutex;
 12     pthread_cond_t pcond;
 13 }condition_t;
 14 
 15 typedef struct task
 16 {
 17     void *(*run)(void *arg);
 18     void *arg;
 19     struct task *next;
 20 }task_t;
 21 
 22 typedef struct threadpool
 23 {
 24     condition_t ready;
 25     task_t *first;
 26     task_t *last;
 27     int counter;
 28     int idle;
 29     int max_threads;
 30     int quit;
 31 }threadpool_t;
 32 
 33 
 34 int condition_init(condition_t *cond)
 35 {
 36     int status;
 37     if((status = pthread_mutex_init(&cond->pmutex,NULL)))//返回0代表初始化成功
 38         return status;
 39     if((status = pthread_cond_init(&cond->pcond,NULL)))
 40         return status;
 41     return 0;
 42 }
 43 int condition_lock(condition_t *cond)
 44 {
 45     return pthread_mutex_lock(&cond -> pmutex);
 46 }
 47 int condition_unlock(condition_t *cond)
 48 {
 49     return pthread_mutex_unlock(&cond -> pmutex);
 50 }
 51 int condition_wait(condition_t *cond)
 52 {
 53     return pthread_cond_wait(&cond -> pcond,&cond -> pmutex);
 54 }
 55 int condition_timewait(condition_t *cond,const struct timespec *abstime)
 56 {
 57     return pthread_cond_timedwait(&cond->pcond,&cond->pmutex,abstime);
 58 }
 59 int condition_signal(condition_t *cond)
 60 {
 61     return pthread_cond_signal(&cond->pcond);
 62 }
 63 int condition_broadcast(condition_t *cond)
 64 {
 65     return pthread_cond_broadcast(&cond -> pcond);
 66 }
 67 int condition_destory(condition_t *cond)
 68 {
 69     int status;
 70     if((status = pthread_mutex_destroy(&cond -> pmutex)))
 71         return status;
 72     if((status = pthread_cond_destroy(&cond -> pcond)))
 73         return status;
 74     return 0;
 75 }
 76 
 77 
 78 void *thread_routine(void *arg)
 79 {
 80     struct timespec abstime;
 81     int timeout;
 82     printf("thread 0x%0x is starting\n",(int)pthread_self());
 83     threadpool_t *pool = (threadpool_t *)arg;
 84     while(1)
 85     {
 86         timeout = 0;
 87         condition_lock(&pool -> ready);
 88         pool -> idle++;
 89         //等待隊列有任務到來或者線程池銷毀的通知
 90         while(pool -> first == NULL && !pool -> quit)
 91         {
 92             printf("thread 0x%0x is waiting\n",(int)pthread_self());
 93             clock_gettime(CLOCK_REALTIME,&abstime);
 94             abstime.tv_sec += 2;
 95             int status=condition_timewait(&pool -> ready,&abstime);
 96             if(status == ETIMEDOUT)
 97             {
 98                 printf("thread 0x%0x is wait timed out\n",(int)pthread_self());
 99                 timeout = 1;
100                 break;
101             }
102 
103         }
104         //等到到條件,處於工作狀態
105         pool -> idle--;
106 
107         if(pool -> first != NULL)
108         {
109             task_t *t = pool -> first;
110             pool -> first = t -> next;
111             //需要先解鎖,以便添加新任務。其他消費者線程能夠進入等待任務。
112             condition_unlock(&pool -> ready);
113             t -> run(t->arg);
114             free(t);
115             condition_lock(&pool -> ready);
116         }
117         //等待線程池銷毀的通知
118         if(pool -> quit && pool ->first == NULL)
119         {
120             pool -> counter--;
121             if(pool->counter == 0)
122             {
123                 condition_signal(&pool -> ready);
124             }
125             condition_unlock(&pool->ready);
126             //跳出循環之前要記得解鎖
127             break;
128         }
129 
130         if(timeout &&pool -> first ==NULL)
131         {
132             pool -> counter--;
133             condition_unlock(&pool->ready);
134             //跳出循環之前要記得解鎖
135             break;
136         }
137         condition_unlock(&pool -> ready);
138     }
139 
140     printf("thread 0x%0x is exiting\n",(int)pthread_self());
141     return NULL;
142 }
143 
144 //初始化
145 void threadpool_init(threadpool_t *pool, int threads)
146 {
147     condition_init(&pool -> ready);
148     pool -> first = NULL;
149     pool -> last = NULL;
150     pool -> counter = 0;
151     pool -> idle = 0;
152     pool -> max_threads = threads;
153     pool -> quit = 0;
154 }
155 
156 //加任務
157 void threadpool_add_task(threadpool_t *pool, void *(*run)(void *arg),void *arg)
158 {
159     task_t *newstask = (task_t *)malloc(sizeof(task_t));
160     newstask->run = run;
161     newstask->arg = arg;
162     newstask -> next = NULL;
163     
164     condition_lock(&pool -> ready);
165     //將任務添加到對列中
166     if(pool -> first ==NULL)
167     {
168         pool -> first = newstask;
169     }
170     else
171         pool -> last -> next = newstask;
172     pool -> last = newstask;
173     //如果有等待線程,則喚醒其中一個
174     if(pool -> idle > 0)
175     {
176         condition_signal(&pool -> ready);
177     }
178     else if(pool -> counter < pool -> max_threads)
179     {
180         pthread_t tid;
181         pthread_create(&tid,NULL,thread_routine,pool);
182         pool -> counter++;
183     }
184     condition_unlock(&pool -> ready);
185 }
186 //銷毀線程池
187 void  threadpool_destory(threadpool_t *pool)
188 {
189 
190     if(pool -> quit)
191     {
192         return;
193     }
194     condition_lock(&pool -> ready);
195     pool->quit = 1;
196     if(pool -> counter > 0)
197     {
198         if(pool -> idle > 0)
199             condition_broadcast(&pool->ready);
200 
201         while(pool -> counter > 0)
202         {
203             condition_wait(&pool->ready);
204         }
205     }
206     condition_unlock(&pool->ready);
207     condition_destory(&pool -> ready);
208 }
209 
210 
211 void *mytask(void *arg)
212 {
213     printf("thread 0x%0x is working on task %d\n",(int)pthread_self(),*(int*)arg);
214     sleep(1);
215     free(arg);
216     return NULL;
217 }
218 int main()
219 {
220     threadpool_t pool;
221     threadpool_init(&pool,3);
222     
223     int i ;
224     for(i = 0; i < 10; i++)
225     {
226         int *arg = (int *)malloc(sizeof(int));
227         *arg = i;
228         threadpool_add_task(&pool,mytask,arg);
229     }
230     
231     sleep(15);//為了等待其他線程結束 當然也可以通過pthread_join來做
232     threadpool_destory(&pool);
233     return 0;
234 }

 

-->代碼下載

    Github

--------------------------------------------------------------------------------------------------------------------------------------

本文是我學習後,一些總結。比較基礎,適合新接觸Linux編程的人學習。請勿轉載。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved