在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 }
-->代码下载
--------------------------------------------------------------------------------------------------------------------------------------
本文是我学习后,一些总结。比较基础,适合新接触Linux编程的人学习。请勿转载。