├── .gitignore ├── LICENSE ├── README.md ├── readConfig.c ├── readConfig.h ├── thread_pool_config.conf ├── threadpool.c ├── threadpool.h └── tip.txt /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | 4 | # Libraries 5 | *.lib 6 | *.a 7 | 8 | # Shared objects (inc. Windows DLLs) 9 | *.dll 10 | *.so 11 | *.so.* 12 | *.dylib 13 | 14 | # Executables 15 | *.exe 16 | *.out 17 | *.app 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | thread_pool 2 | =========== 3 | 4 | advanced thread pools with dynamic adjustment 5 | 6 | look for the url:http://blog.csdn.net/lingfengtengfei/article/details/9038633 7 | and http://blog.csdn.net/lingfengtengfei/article/details/9039135 8 | 9 | -------------------------------------------------------------------------------- /readConfig.c: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | * filename:readConfig.c 3 | * author:mkirin 4 | * e-mail:lingfengtengfei@163.com 5 | * description: reading the thread config file 6 | * 读取配置文件 7 | * 8 | * 1、 通过 char *GetParamValue(char *cpConfFile, 9 | * char *cpParam, char *cpValue) 10 | * 函数获取指定配置文件中的指定参数的值,保存 11 | * 在cpValue中 12 | * 2、 配置文件风格说明: 13 | * (1) 自动忽略掉每行开头的空格 14 | * (2) 以 # 开头的行是注释行 15 | * (3) 不能以 = 开头 16 | * (4) 支持行末注释 17 | ***************************************************/ 18 | #include "readConfig.h" 19 | 20 | 21 | /* function name: GetMaxLineLen 22 | * function parameter : 23 | * cpFileName: the thread pool config file's full path (with filename) 24 | * function description: to get the thread pool config file's size of the max line(获取指定文件中最长的行的长度) 25 | * returned value: the size of max line 26 | */ 27 | static unsigned long GetMaxLineLen(char *cpFileName) 28 | { 29 | FILE *fpFile = NULL; 30 | unsigned long ulMaxLineLen = 0; 31 | unsigned long ulCntLineLen = 0; 32 | char cCh = EOF; 33 | 34 | /*打开文件*/ 35 | fpFile = fopen(cpFileName, "r"); 36 | if(NULL == fpFile) 37 | { 38 | return 0; 39 | } 40 | 41 | /*逐行读取文件,遇到'/n'结束一行*/ 42 | while(1) 43 | { 44 | cCh = fgetc(fpFile); 45 | if(EOF == cCh) 46 | { 47 | if(ulCntLineLen > ulMaxLineLen) 48 | { 49 | ulMaxLineLen = ulCntLineLen; 50 | ulCntLineLen = 0; 51 | } 52 | break; 53 | } 54 | ulCntLineLen++; 55 | if('/n' == cCh) 56 | { 57 | if(ulCntLineLen > ulMaxLineLen) 58 | { 59 | ulMaxLineLen = ulCntLineLen; 60 | ulCntLineLen = 0; 61 | } 62 | ulCntLineLen = 0; 63 | } 64 | } 65 | 66 | fclose(fpFile); 67 | 68 | return ulMaxLineLen; 69 | } 70 | 71 | 72 | /* function name: TrimLeft 73 | * function parameter : 74 | * cpString: any strings 75 | * function description: remove the string at the beginning of the blank character(去掉字符串开头的空白字符) 76 | * returned value: the pointer to the string 77 | */ 78 | static char *TrimLeft(char *cpString) 79 | { 80 | char *cpRet = NULL; 81 | 82 | /*过滤空字符串*/ 83 | if('\0' == *cpString) 84 | { 85 | return cpString; 86 | } 87 | 88 | /*忽略头部的 空格 '/r' '/n' '/t'*/ 89 | cpRet = cpString; 90 | while(' ' == *cpRet || '\t' == *cpRet || '\r' == *cpRet || '\n' == *cpRet) 91 | { 92 | cpRet++; 93 | } 94 | 95 | return cpRet; 96 | } 97 | 98 | 99 | /* function name: TrimRight 100 | * function parameter : 101 | * cpString: any strings 102 | * function description: remove the string at the end of the blank character(去掉字符串末尾的空白字符) 103 | * returned value: the pointer to the string 104 | */ 105 | static void TrimRight(char *cpString) 106 | { 107 | unsigned long ulStrLen = 0; 108 | 109 | /*过滤空字符串*/ 110 | if('\0' == *cpString) 111 | { 112 | return; 113 | } 114 | 115 | /*去掉尾部的 空格 '/r' '/n' '/t'*/ 116 | ulStrLen = strlen(cpString); 117 | while(' ' == cpString[ulStrLen - 1] || '\t' == cpString[ulStrLen - 1] 118 | || '\r' == cpString[ulStrLen - 1] || '\n' == cpString[ulStrLen - 1]) 119 | { 120 | ulStrLen--; 121 | } 122 | cpString[ulStrLen] = '\0'; 123 | } 124 | 125 | 126 | /* function name: TrimStr 127 | * function parameter : 128 | * cpString: any strings 129 | * function description: remove the string at the beginning of the blank character 130 | * and remove the string at the end of the blank character(去掉字符串开头和末尾的空白字符) 131 | * returned value: the pointer to the string 132 | */ 133 | static char *TrimStr(char *cpString) 134 | { 135 | char *cpRet = NULL; 136 | 137 | TrimRight(cpString); 138 | cpRet = TrimLeft(cpString); 139 | 140 | return cpRet; 141 | } 142 | 143 | 144 | /* function name: ParseLine 145 | * function parameter : 146 | * cpLine: any strings of any lines 147 | * cpParam: The specified parameter name 148 | * cpValue:The specified parameter value 149 | * function description: From the value of parameter specifies the parameter name string in a given string line 150 | (从给定行字符串中解析出指定参数名的参数值) 151 | * returned value: the pointer to the specified parameter value 152 | */ 153 | static char *ParseLine(char *cpLine, char *cpParam, char *cpValue) 154 | { 155 | char *cpTmp = NULL; 156 | char *cpPtr = NULL; 157 | unsigned long ulSepLoc = 0; 158 | 159 | /*去掉行首的空格*/ 160 | cpTmp = TrimLeft(cpLine); 161 | 162 | /*过滤注释行,即以 # 开头的行, 第一个字符不可以是 = */ 163 | if('#' == *cpTmp || '=' == *cpTmp) 164 | { 165 | return NULL; 166 | } 167 | 168 | /*查找 # 号,移除行末注释*/ 169 | ulSepLoc = 0; 170 | while(ulSepLoc < strlen(cpTmp)) 171 | { 172 | if('#' == cpTmp[ulSepLoc]) 173 | { 174 | break; 175 | } 176 | ulSepLoc++; 177 | } 178 | cpTmp[ulSepLoc] = '\0'; 179 | 180 | /*查找 = */ 181 | ulSepLoc = 0; 182 | while(ulSepLoc < strlen(cpTmp)) 183 | { 184 | if('=' == cpTmp[ulSepLoc]) 185 | { 186 | break; 187 | } 188 | ulSepLoc++; 189 | } 190 | if(ulSepLoc == strlen(cpTmp)) 191 | { 192 | return NULL; 193 | } 194 | 195 | /*获取参数*/ 196 | cpTmp[ulSepLoc] = '\0'; 197 | cpPtr = TrimStr(cpTmp); 198 | if(strcmp(cpPtr, cpParam)) 199 | { 200 | return NULL; 201 | } 202 | 203 | /*获取参数的值*/ 204 | cpPtr = TrimStr(cpTmp + ulSepLoc + 1); 205 | strcpy(cpValue, cpPtr); 206 | 207 | return cpValue; 208 | } 209 | 210 | 211 | /*从指定配置文件中获取指定参数名的参数值*/ 212 | /* function name: GetParamValue 213 | * function parameter : 214 | * cpConfFile: the config file's full path (with filename) 215 | * cpParam: The specified parameter name 216 | * cpValue:The specified parameter value 217 | * function description: From the value of parameter specifies the parameter name string in a given config file 218 | (从指定配置文件中获取指定参数名的参数值) 219 | * returned value: the pointer to the specified parameter value 220 | */ 221 | char *GetParamValue(char *cpConfFile, char *cpParam, char *cpValue) 222 | { 223 | FILE *fpConf = NULL; 224 | char *cpLine = NULL; 225 | char *cpRet = NULL; 226 | char cCh = EOF; 227 | unsigned long ulMaxLineLen = 0; 228 | unsigned long ulLineLen = 0; 229 | 230 | /*获取最大行长度*/ 231 | ulMaxLineLen = GetMaxLineLen(cpConfFile); 232 | if(0 == ulMaxLineLen) 233 | { 234 | return NULL; 235 | } 236 | 237 | /*打开文件*/ 238 | fpConf = fopen(cpConfFile, "r"); 239 | if(NULL == fpConf) 240 | { 241 | return NULL; 242 | } 243 | 244 | /*分配内存*/ 245 | cpLine = (char *)malloc(ulMaxLineLen + 1); 246 | if(NULL == cpLine) 247 | { 248 | fclose(fpConf); 249 | return NULL; 250 | } 251 | 252 | /*逐行读取并分析*/ 253 | ulLineLen = 0; 254 | while(1) 255 | { 256 | cCh = fgetc(fpConf); 257 | switch(cCh) 258 | { 259 | case '\n': 260 | cpLine[ulLineLen++] = cCh; 261 | cpLine[ulLineLen++] = '\0'; 262 | if(NULL != (cpRet = ParseLine(cpLine, cpParam, cpValue))) 263 | { 264 | break; 265 | } 266 | ulLineLen = 0; 267 | break; 268 | 269 | case EOF: 270 | cpLine[ulLineLen++] = '\0'; 271 | if(NULL != (cpRet = ParseLine(cpLine, cpParam, cpValue))) 272 | { 273 | break; 274 | } 275 | ulLineLen = 0; 276 | break; 277 | 278 | default: 279 | cpLine[ulLineLen++] = cCh; 280 | break; 281 | } 282 | 283 | if(NULL != cpRet || EOF == cCh) 284 | { 285 | break; 286 | } 287 | } 288 | 289 | /*释放内存、关闭文件*/ 290 | free(cpLine); 291 | fclose(fpConf); 292 | 293 | return cpRet; 294 | } 295 | /* 296 | following just a test…… 297 | 298 | */ 299 | /* 300 | int g_def_thread_num = 0; 301 | 302 | int g_manage_adjust_interval = 0; 303 | int g_max_thread_num = 0; 304 | int g_min_thread_num = 0; 305 | int g_thread_worker_high_ratio = 0; 306 | int g_thread_worker_low_ratio = 0; 307 | int get_config_value(char *item) 308 | { 309 | char value[50] = {0}; 310 | printf("+++++%s\n",item); 311 | if(GetParamValue("thread_pool_config.conf",item,value) == NULL) 312 | { 313 | return -1; 314 | } 315 | printf("%s = %s\n",item,value); 316 | return atoi(value); 317 | } 318 | 319 | void conf_init() 320 | { 321 | g_max_thread_num = get_config_value("MAX_THREAD_NUM"); 322 | g_min_thread_num = get_config_value("MIN_THREAD_NUM"); 323 | g_def_thread_num = get_config_value("DEF_THREAD_NUM"); 324 | g_manage_adjust_interval = get_config_value("MANAGE_ADJUST_INTERVAL"); 325 | g_thread_worker_high_ratio = get_config_value("THREAD_WORKER_HIGH_RATIO"); 326 | g_thread_worker_low_ratio = get_config_value("THREAD_WORKER_LOW_RATIO"); 327 | 328 | } 329 | 330 | int main() 331 | { 332 | conf_init(); 333 | return 0; 334 | } 335 | */ 336 | -------------------------------------------------------------------------------- /readConfig.h: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | * filename:readConfig.h 3 | * author:mkirin 4 | * e-mail:lingfengtengfei@163.com 5 | * description: reading the thread config file's header file 6 | * 读取配置文件 7 | * 8 | * 1、 通过 char *GetParamValue(char *cpConfFile, 9 | * char *cpParam, char *cpValue) 10 | * 函数获取指定配置文件中的指定参数的值,保存 11 | * 在cpValue中 12 | * 2、 配置文件风格说明: 13 | * (1) 自动忽略掉每行开头的空格 14 | * (2) 以 # 开头的行是注释行 15 | * (3) 不能以 = 开头 16 | * (4) 支持行末注释 17 | ***************************************************/ 18 | #ifndef _READCONFIG_HEAD_ 19 | #define _READCONFIG_HEAD_ 20 | 21 | #include 22 | #include 23 | #include 24 | char *GetParamValue(char *cpConfFile, char *cpParam, char *cpValue); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /thread_pool_config.conf: -------------------------------------------------------------------------------- 1 | #线程池配置文件filename:[thread_pool_config.conf] 其中‘#’为注释 不准以=开始 2 | 3 | #线程池最小线程数 4 | MIN_THREAD_NUM = 3 5 | 6 | #线程池最大线程数 7 | MAX_THREAD_NUM =50 8 | 9 | #线程池默认线程数 10 | DEF_THREAD_NUM = 25 11 | 12 | #管理线程动态调节时间间隔(s) 13 | MANAGE_ADJUST_INTERVAL = 5 14 | 15 | #线程数与任务峰值比例 16 | THREAD_WORKER_HIGH_RATIO = 3 17 | 18 | #任务数与线程数低谷比例 19 | THREAD_WORKER_LOW_RATIO = 1 20 | -------------------------------------------------------------------------------- /threadpool.c: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | * filename:thread_pool.c 3 | * author:mkirin 4 | * e-mail:lingfengtengfei@163.com 5 | * data:2013-5-18 6 | * description:the major implement of the thread pool 7 | ****************************************************/ 8 | 9 | 10 | #include "threadpool.h" 11 | 12 | /**************** 全局变量定义区 ***************/ 13 | 14 | thread_pool *g_pool = NULL; 15 | thread_revoke *g_thread_revoke = NULL; 16 | int g_def_thread_num = 0; 17 | int g_manage_adjust_interval = 0; 18 | int g_max_thread_num = 0; 19 | int g_min_thread_num = 0; 20 | int g_thread_worker_high_ratio = 0; 21 | int g_thread_worker_low_ratio = 0; 22 | 23 | 24 | /** 函数名: get_config_value int 的项值 25 | * 功能描述: 获取配置文件中某一项的值 26 | * 参数列表: item:为配置文件中的项名 27 | * 返回值: 出错返回-1 成功返回项的值 28 | */ 29 | int get_config_value(char *item) 30 | { 31 | char value[50]; 32 | if(GetParamValue(CONFIGFILENAME,item,value) == NULL) 33 | { 34 | return -1; 35 | } 36 | 37 | return atoi(value); 38 | } 39 | 40 | 41 | /** 函数名: get_config_value int 的项值 42 | * 功能描述: 初始化配置文件项变量的值 43 | * 参数列表: 无 44 | * 返回值: 无 45 | */ 46 | void conf_init() 47 | { 48 | g_max_thread_num = get_config_value(MAX_THREAD_NUM); 49 | g_min_thread_num = get_config_value(MIN_THREAD_NUM); 50 | g_def_thread_num = get_config_value(DEF_THREAD_NUM); 51 | g_manage_adjust_interval = get_config_value(MANAGE_ADJUST_INTERVAL); 52 | g_thread_worker_high_ratio = get_config_value(THREAD_WORKER_HIGH_RATIO); 53 | g_thread_worker_low_ratio = get_config_value(THREAD_WORKER_LOW_RATIO); 54 | 55 | } 56 | 57 | /** 函数名: pool_init 58 | * 功能描述: 初始化线程池 59 | * 参数列表: max_thread_num :输入要建的线程池的线程最大数目 60 | * 返回值: 无 61 | */ 62 | void pool_init(int max_thread_num) 63 | { 64 | int i; 65 | conf_init(); 66 | if(max_thread_num < g_min_thread_num) 67 | { 68 | max_thread_num = g_min_thread_num; 69 | } 70 | else if(max_thread_num > g_max_thread_num) 71 | { 72 | max_thread_num = g_max_thread_num; 73 | } 74 | pthread_attr_t attr; 75 | int err; 76 | err= pthread_attr_init(&attr); 77 | if(err != 0) 78 | { 79 | perror("pthread_attr_init"); 80 | exit(1); 81 | } 82 | err = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); 83 | 84 | if(err != 0) 85 | { 86 | perror("pthread_attr_setdetachstate"); 87 | exit(1); 88 | } 89 | 90 | g_pool = (thread_pool *)malloc(sizeof(thread_pool)); 91 | 92 | pthread_mutex_init(&(g_pool->queue_lock),NULL); 93 | pthread_mutex_init(&(g_pool->remove_queue_lock),NULL); 94 | pthread_cond_init(&(g_pool->queue_ready),NULL); 95 | 96 | g_pool->queue_head = NULL; 97 | g_pool->max_thread_num = max_thread_num; 98 | g_pool->thread_queue =NULL; 99 | g_pool->thread_idle_queue = NULL; 100 | g_pool->idle_queue_num = 0; 101 | g_pool->cur_queue_size = 0; 102 | g_pool->shutdown = 0; 103 | 104 | int temp; 105 | for(i = 0; i < max_thread_num; i++) 106 | { 107 | pthread_t thread_id; 108 | pthread_create(&thread_id,&attr,thread_routine,NULL); 109 | thread_queue_add_node(&(g_pool->thread_queue),thread_id,&temp); 110 | printf("temp&&&&&&&&&&&&&%d\n",temp); 111 | 112 | } 113 | 114 | pthread_attr_destroy(&attr); 115 | 116 | } 117 | /* 118 | 线程取消函数 119 | */ 120 | void thread_revoke_init() 121 | { 122 | g_thread_revoke = (thread_revoke *)malloc(sizeof(thread_revoke)); 123 | 124 | pthread_mutex_init(&(g_thread_revoke->revoke_mutex),NULL); 125 | g_thread_revoke->thread_revoke_queue = NULL; 126 | g_thread_revoke->revoke_count = 0; 127 | g_thread_revoke->is_revoke = 0; 128 | g_thread_revoke->revoke_num = 0; 129 | } 130 | /** 函数名: thread_queue_add_node 131 | 132 | * 功能描述: 向线程池中新增线程 133 | * 参数列表: thread_queue:要增加的线程的线程队列 thread_id:线程的id 134 | * 返回值: 成功返回0 失败返回1 135 | */ 136 | int thread_queue_add_node(p_thread_queue_node *thread_queue,pthread_t thread_id,int *count) 137 | { 138 | pthread_mutex_lock(&(g_pool->remove_queue_lock)); 139 | printf("++++count:%d++++++add thread id :%u++++\n",*count,thread_id); 140 | thread_queue_node *p = *thread_queue; 141 | thread_queue_node *new_node = (thread_queue_node *)malloc(sizeof(thread_queue_node)); 142 | if(NULL == new_node) 143 | { 144 | printf("malloc for new thread queue node failed!\n"); 145 | pthread_mutex_unlock(&(g_pool->remove_queue_lock)); 146 | return 1; 147 | } 148 | 149 | new_node->thread_id = thread_id; 150 | new_node->next = NULL; 151 | 152 | /*如果队列为空*/ 153 | if(NULL == *(thread_queue)) 154 | { 155 | *(thread_queue) = new_node; 156 | (*count)++; 157 | pthread_mutex_unlock(&(g_pool->remove_queue_lock)); 158 | return 0; 159 | } 160 | 161 | /*每次都将新节点插入到队列头部*/ 162 | new_node->next = p; 163 | *(thread_queue) = new_node; 164 | (*count)++; 165 | pthread_mutex_unlock(&(g_pool->remove_queue_lock)); 166 | return 0; 167 | } 168 | int thread_queue_remove_node(p_thread_queue_node *thread_queue,pthread_t thread_id,int *count) 169 | { 170 | 171 | pthread_mutex_lock(&(g_pool->remove_queue_lock)); 172 | printf("---count:%d------remove threadid : %u----\n",*count,thread_id); 173 | p_thread_queue_node current_node,pre_node; 174 | if(NULL == *(thread_queue)) 175 | { 176 | printf("revoke a thread node from queue failed!\n"); 177 | pthread_mutex_unlock(&(g_pool->remove_queue_lock)); 178 | return 1; 179 | } 180 | 181 | current_node = *(thread_queue); 182 | pre_node = *(thread_queue); 183 | int i = 1; 184 | while(i < g_pool->max_thread_num && current_node != NULL) 185 | { 186 | printf("i = %d, max_thread_num = %d \n",i,g_pool->max_thread_num); 187 | i++; 188 | if(thread_id == current_node->thread_id) 189 | { 190 | break; 191 | } 192 | pre_node = current_node; 193 | current_node = current_node->next; 194 | 195 | } 196 | 197 | if(NULL == current_node) 198 | { 199 | printf("revoke a thread node from queue failed!\n"); 200 | pthread_mutex_unlock(&(g_pool->remove_queue_lock)); 201 | return 1; 202 | } 203 | 204 | /*找到该线程的位置,删除对应的线程节点 如果要删除的节点就是头节点 */ 205 | if(current_node->thread_id == (*(thread_queue))->thread_id) 206 | { 207 | *(thread_queue) = (*(thread_queue))->next; 208 | free(current_node); 209 | (*count)--; 210 | pthread_mutex_unlock(&(g_pool->remove_queue_lock)); 211 | return 0; 212 | } 213 | 214 | /*找到该线程的位置,删除对应的线程节点 如果要删除的节点就是尾节点 */ 215 | if(current_node->next == NULL) 216 | { 217 | pre_node->next =NULL; 218 | free(current_node); 219 | (*count)--; 220 | pthread_mutex_unlock(&(g_pool->remove_queue_lock)); 221 | return 0; 222 | } 223 | pre_node = current_node->next; 224 | free(current_node); 225 | (*count)--; 226 | printf("0 max_thread_num = %d\n",g_pool->max_thread_num); 227 | pthread_mutex_unlock(&(g_pool->remove_queue_lock)); 228 | return 0; 229 | } 230 | 231 | 232 | /** 函数名: pool_add_worker 233 | * 功能描述: 向线程池中加任务 234 | * 参数列表: process :函数指针,指向处理函数用作真正的工作处理 235 | * arg:工作队列中的参数 236 | * 返回值: 成功返回0,失败返回-1 237 | */ 238 | int pool_add_worker(void*(*process)(void *arg),void *arg) 239 | { 240 | thread_worker *new_work = (thread_worker *)malloc(sizeof(thread_worker)); 241 | 242 | if(new_work == NULL) 243 | { 244 | return -1; 245 | } 246 | 247 | new_work->process = process; 248 | new_work->arg = arg; 249 | new_work->next = NULL; 250 | 251 | pthread_mutex_lock(&(g_pool->queue_lock)); 252 | 253 | /*将任务加入等待队列中*/ 254 | thread_worker *member = g_pool->queue_head; 255 | if(member != NULL) 256 | { 257 | while(member->next != NULL) 258 | { 259 | member = member->next; 260 | } 261 | 262 | member->next = new_work; 263 | } 264 | else 265 | { 266 | g_pool->queue_head = new_work; 267 | } 268 | 269 | assert(g_pool->queue_head != NULL); 270 | 271 | g_pool->cur_queue_size++; 272 | pthread_mutex_unlock(&(g_pool->queue_lock)); 273 | /*等待队列中有新任务了,唤醒一个等待线程处理任务;注意,如果所有的线程都在忙碌,这句话没有任何作用*/ 274 | pthread_cond_signal(&(g_pool->queue_ready)); 275 | 276 | return 0; 277 | } 278 | 279 | /** 函数名: pool_add_thread 280 | 281 | * 功能描述: 向线程池中新增线程 282 | * 参数列表: thread_num:要增加的线程数目 283 | * 返回值: 无 284 | */ 285 | void pool_add_thread(int thread_num) 286 | { 287 | int i; 288 | pthread_attr_t attr; 289 | int err = pthread_attr_init(&attr); 290 | if(err != 0) 291 | { 292 | perror("pthread_attr_init"); 293 | exit(1); 294 | } 295 | err = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); 296 | 297 | if(err != 0) 298 | { 299 | perror("pthread_attr_setdetachstate"); 300 | exit(1); 301 | } 302 | 303 | for(i = 0; i < thread_num; i++) 304 | { 305 | pthread_t thread_id; 306 | pthread_create(&thread_id,&attr,thread_routine,NULL); 307 | thread_queue_add_node(&(g_pool->thread_queue),thread_id,&(g_pool->max_thread_num)); 308 | } 309 | 310 | pthread_attr_destroy(&attr); 311 | } 312 | 313 | /** 函数名: pool_revoke_thread 314 | * 功能描述: 从线程池线程中撤销线程 315 | * 参数列表: thread_num:要撤销的线程数目 316 | * 返回值: 无 317 | */ 318 | void pool_revoke_thread(int thread_num) 319 | { 320 | if(thread_num == 0) 321 | { 322 | return; 323 | } 324 | 325 | g_thread_revoke->revoke_num =thread_num; 326 | g_thread_revoke->is_revoke = 1; 327 | printf("----max_thread_num %d---------revoke %d thread-----\n",g_pool->max_thread_num,thread_num); 328 | thread_queue_node * p = g_thread_revoke->thread_revoke_queue; 329 | 330 | pthread_cond_broadcast(&(g_pool->queue_ready)); 331 | 332 | } 333 | 334 | void * thread_manage(void *arg) 335 | { 336 | int optvalue; 337 | int thread_num; 338 | while(1) 339 | { 340 | 341 | if(g_pool->cur_queue_size > g_thread_worker_high_ratio * g_pool->max_thread_num) 342 | { 343 | optvalue = 1; 344 | thread_num =(g_pool->cur_queue_size -g_thread_worker_high_ratio * g_pool->max_thread_num) / g_thread_worker_high_ratio; 345 | } 346 | else if (g_pool->cur_queue_size * g_thread_worker_low_ratio < g_pool->max_thread_num) 347 | { 348 | optvalue = 2; 349 | thread_num =(g_pool->max_thread_num -g_thread_worker_low_ratio * g_pool->cur_queue_size) / g_thread_worker_low_ratio; 350 | } 351 | 352 | if(1 == optvalue) 353 | { 354 | 355 | if(g_pool->max_thread_num + thread_num > g_max_thread_num) 356 | { 357 | thread_num = g_max_thread_num - g_pool->max_thread_num; 358 | } 359 | pool_add_thread(thread_num); 360 | 361 | } 362 | else if( 2 == optvalue) 363 | { 364 | if(g_pool->max_thread_num - thread_num < g_min_thread_num) 365 | { 366 | thread_num = g_pool->max_thread_num - g_min_thread_num; 367 | } 368 | // pthread_t revoke_tid; 369 | // pthread_create(&revoke_tid,NULL,(void *)pool_revoke_thread,(void *)thread_num); 370 | pool_revoke_thread(thread_num); 371 | } 372 | 373 | printf("==========ManageThread=============\n"); 374 | 375 | printf("cur_queue_size = %d | max_thread_num = %d\n",g_pool->cur_queue_size,g_pool->max_thread_num); 376 | conf_init(); 377 | sleep(g_manage_adjust_interval); 378 | } 379 | 380 | 381 | 382 | 383 | 384 | } 385 | 386 | 387 | /** 函数名: pool_destroy 388 | * 功能描述: 销毁线程池 389 | * 参数列表: 无 390 | * 返回值: 成功返回0,失败返回-1 391 | */ 392 | int pool_destroy() 393 | { 394 | if(g_pool->shutdown) 395 | { 396 | return -1; 397 | } 398 | 399 | g_pool->shutdown = 1; 400 | 401 | /* 唤醒所有等待线程,线程池要销毁 */ 402 | pthread_cond_broadcast(&(g_pool->queue_ready)); 403 | 404 | /* 阻塞等待线程退出,防止成为僵尸 */ 405 | thread_queue_node * q = g_pool->thread_queue; 406 | thread_queue_node * p = q; 407 | 408 | g_pool->thread_queue = NULL; 409 | 410 | /* 销毁等待队列 */ 411 | thread_worker *head = NULL; 412 | 413 | while(g_pool->queue_head != NULL) 414 | { 415 | head = g_pool->queue_head; 416 | g_pool->queue_head = g_pool->queue_head->next; 417 | free(head); 418 | } 419 | 420 | g_pool->queue_head = NULL; 421 | 422 | /* 条件变量和互斥量销毁 */ 423 | pthread_mutex_destroy(&(g_pool->queue_lock)); 424 | pthread_mutex_destroy(&(g_pool->remove_queue_lock)); 425 | pthread_cond_destroy(&(g_pool->queue_ready)); 426 | 427 | /* 销毁整个线程池 */ 428 | free(g_pool); 429 | g_pool = NULL; 430 | 431 | return 0; 432 | 433 | } 434 | 435 | void cleanup(void *arg) 436 | { 437 | thread_queue_remove_node(&(g_pool->thread_queue),pthread_self(),&(g_pool->max_thread_num)); 438 | pthread_mutex_unlock(&(g_pool->queue_lock)); 439 | printf("thread ID %d will exit\n",pthread_self()); 440 | 441 | } 442 | 443 | /** 函数名: thread_routine 444 | * 功能描述: 线程池中的线程 445 | * 参数列表: arg 线程附带参数 一般为NULL; 446 | * 返回值: 447 | */ 448 | void * thread_routine(void *arg) 449 | { 450 | printf("starting thread ID:%u\n",pthread_self()); 451 | while(1) 452 | { 453 | pthread_mutex_lock(&(g_pool->queue_lock)); 454 | /* 如果等待队列为0 并且不销毁线程池,则处于阻塞状态 455 | *pthread_cond_wait 是原子操作,等待前解锁,唤醒后加锁 456 | */ 457 | 458 | while(g_pool->cur_queue_size == 0 && !g_pool->shutdown ) 459 | { 460 | printf("thread ID %u is waiting \n",pthread_self()); 461 | pthread_cond_wait(&(g_pool->queue_ready),&(g_pool->queue_lock)); 462 | } 463 | 464 | /* 如果线程池要销毁 */ 465 | if(g_pool->shutdown) 466 | { 467 | thread_queue_remove_node(&(g_pool->thread_queue),pthread_self(),&(g_pool->max_thread_num)); 468 | pthread_mutex_unlock(&(g_pool->queue_lock)); 469 | printf("thread ID %d will exit\n",pthread_self()); 470 | pthread_exit(NULL); 471 | } 472 | 473 | if(g_thread_revoke->is_revoke != 0 && g_thread_revoke->revoke_count < g_thread_revoke->revoke_num) 474 | { 475 | /* if(g_thread_revoke->revoke_count >= g_thread_revoke->revoke_num ) 476 | { 477 | 478 | printf("-revoke-@@jie锁@@+++\n"); 479 | pthread_mutex_unlock(&(g_pool->queue_lock)); 480 | continue; 481 | }*/ 482 | thread_queue_remove_node(&(g_pool->thread_queue),pthread_self(),&(g_pool->max_thread_num)); 483 | 484 | thread_queue_add_node(&(g_thread_revoke->thread_revoke_queue),pthread_self(),&(g_thread_revoke->revoke_count)); 485 | g_thread_revoke->revoke_count++; 486 | pthread_mutex_unlock(&(g_pool->queue_lock)); 487 | printf("revoke success thread ID %d will exit\n",pthread_self()); 488 | pthread_exit(NULL); 489 | 490 | } 491 | 492 | printf("thread ID %u is starting to work\n",pthread_self()); 493 | assert(g_pool->cur_queue_size != 0); 494 | assert(g_pool->queue_head != NULL); 495 | 496 | /* 等待队列长度减1,并且取出链表的头元素 */ 497 | g_pool->cur_queue_size--; 498 | thread_worker * worker = g_pool->queue_head; 499 | g_pool->queue_head = worker->next; 500 | pthread_mutex_unlock(&(g_pool->queue_lock)); 501 | printf("************执行任务\n"); 502 | /* 调用回调函数,执行任务 */ 503 | (*(worker->process))(worker->arg); 504 | free(worker); 505 | worker = NULL; 506 | 507 | } 508 | pthread_exit(NULL); 509 | } 510 | 511 | void *myprocess(void *arg) 512 | { 513 | printf("thread ID is %u, working on task%d\n",pthread_self(),*(int *)arg); 514 | sleep(1); 515 | return NULL; 516 | } 517 | 518 | int main(int argc, char * argv[]) 519 | { 520 | pthread_t manage_tid; 521 | thread_revoke_init(); 522 | sleep(1); 523 | pool_init(g_def_thread_num); 524 | sleep(3); 525 | pthread_create(&manage_tid,NULL,thread_manage,NULL); 526 | // int *workingnum = (int *)malloc(sizeof(int)*1000); 527 | int i; 528 | for(i = 0; ; i++) 529 | { 530 | 531 | pool_add_worker(myprocess,&i); 532 | i++; 533 | pool_add_worker(myprocess,&i); 534 | i++; 535 | pool_add_worker(myprocess,&i); 536 | i++; 537 | pool_add_worker(myprocess,&i); 538 | sleep(1); 539 | if(i%8== 0) 540 | { 541 | sleep(10); 542 | } 543 | 544 | if(i%10 == 0) 545 | { 546 | sleep(20); 547 | } 548 | } 549 | 550 | sleep(5); 551 | printf("=======xiaohui========\n"); 552 | pool_destroy(); 553 | 554 | // free(workingnum); 555 | return 0; 556 | } 557 | -------------------------------------------------------------------------------- /threadpool.h: -------------------------------------------------------------------------------- 1 | 2 | /*************************************************** 3 | * filename:thread_pool.h 4 | * author:mkirin 5 | * e-mail:lingfengtengfei@163.com 6 | * description: the thread pool's header 7 | ***************************************************/ 8 | 9 | #ifndef _THREADPOOL_HEAD_ 10 | #define _THREADPOOL_HEAD_ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include "readConfig.h" 19 | 20 | /**********************宏定义区********************/ 21 | 22 | /* 配置文件名 */ 23 | #define CONFIGFILENAME "thread_pool_config.conf" 24 | 25 | /* 线程池最小线程数 */ 26 | #define MIN_THREAD_NUM "MIN_THREAD_NUM" 27 | 28 | /* 线程池最大线程数 */ 29 | #define MAX_THREAD_NUM "MAX_THREAD_NUM" 30 | 31 | /* 线程池默认线程数 */ 32 | #define DEF_THREAD_NUM "DEF_THREAD_NUM" 33 | 34 | /* 管理线程动态调节时间间隔(s) */ 35 | #define MANAGE_ADJUST_INTERVAL "MANAGE_ADJUST_INTERVAL" 36 | 37 | /* 线程数与工作峰值比例 */ 38 | #define THREAD_WORKER_HIGH_RATIO "THREAD_WORKER_HIGH_RATIO" 39 | 40 | /* 任务与线程数低谷比例 */ 41 | #define THREAD_WORKER_LOW_RATIO "THREAD_WORKER_LOW_RATIO" 42 | 43 | 44 | 45 | 46 | 47 | /************************结构体声明区*************************/ 48 | 49 | /* 50 | *线程池里所有运行和等待的任务都是 一个thread_worker 51 | *由于所有任务都在链表中,所以是一个链表结构 52 | */ 53 | typedef struct _worker{ 54 | void *(*process)(void *arg); /* 工作的处理函数指针 */ 55 | void *arg; /* 处理函数的参数 */ 56 | struct _worker *next; /* 下一个工作 */ 57 | }thread_worker; 58 | 59 | /* 线程队列节点结构 */ 60 | typedef struct _thread_queue_node{ 61 | pthread_t thread_id; 62 | struct _thread_queue_node *next; 63 | }thread_queue_node,*p_thread_queue_node; 64 | 65 | /* 线程池结构 */ 66 | typedef struct { 67 | int shutdown; /* 是否销毁线程池 */ 68 | pthread_mutex_t queue_lock; /* 线程锁 */ 69 | pthread_mutex_t remove_queue_lock; /* 线程锁 */ 70 | pthread_cond_t queue_ready; /* 通知等待队列有新任务条件变量 */ 71 | thread_queue_node *thread_queue; /* 线程池的线程队列 */ 72 | thread_queue_node *thread_idle_queue; 73 | int idle_queue_num; 74 | int max_thread_num; /* 线程池中允许开启的最大线程数 */ 75 | int cur_queue_size; /* 当前等待队列的任务数目 */ 76 | thread_worker *queue_head; /* 线程池所有等待任务 */ 77 | }thread_pool; 78 | 79 | /* 线程取消 */ 80 | typedef struct { 81 | int is_revoke; /*是否需要撤销线程*/ 82 | int revoke_count; /* 已经撤销的线程数 */ 83 | int revoke_num; /* 需要撤销的总数 */ 84 | pthread_mutex_t revoke_mutex; /* 撤销线程加锁 */ 85 | thread_queue_node *thread_revoke_queue; /* 线程撤销队列 */ 86 | }thread_revoke; 87 | 88 | /**************************功能函数声明区************************/ 89 | 90 | /** 向线程池中添加任务 **/ 91 | int pool_add_worker(void *(*process)(void *arg), void *arg); 92 | 93 | /** 线程池中的线程 **/ 94 | void *thread_routine(void *arg); 95 | 96 | /** 初始化线程池 **/ 97 | void pool_init(int max_thread_num); 98 | 99 | /** 销毁线程池 **/ 100 | int pool_destroy(); 101 | 102 | /** 向线程池中追加线程 **/ 103 | void pool_add_thread(int thread_num); 104 | 105 | /** 向线程队列中追加线程 **/ 106 | int thread_queue_add_node(p_thread_queue_node *thread_queue, pthread_t thread_id,int * count); 107 | 108 | /** 撤销线程 **/ 109 | void pool_revoke_thread(int thread_num); 110 | 111 | /** 从线程队列删除线程 **/ 112 | int thread_queue_remove_node(p_thread_queue_node *thread_queue, pthread_t thread_id,int *count); 113 | 114 | /** 获取配置文件中某一项的值 **/ 115 | int get_config_value(char * item); 116 | 117 | /*****************全局变量声明区******************/ 118 | /* 线程池 */ 119 | extern thread_pool *g_pool; 120 | 121 | /* 线程取消 */ 122 | extern thread_revoke *g_thread_revoke; 123 | 124 | /* 线程池最大线程数 */ 125 | extern int g_max_thread_num; 126 | 127 | /* 线程池最小线程数 */ 128 | extern int g_min_thread_num; 129 | 130 | /* 默认线程池线程数 */ 131 | extern int g_def_thread_num; 132 | 133 | /* 管理线程调整时间间隔 */ 134 | extern int g_manage_adjust_interval; 135 | 136 | /* 线程任务峰值比率:衡量负载 */ 137 | extern int g_thread_worker_high_ratio; 138 | 139 | /* 线程任务低谷比率:衡量负载 */ 140 | extern int g_thread_worker_low_ratio; 141 | 142 | #endif 143 | -------------------------------------------------------------------------------- /tip.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkirin/thread_pool/488d066a548aebfa547b0cc1fe5cd4a66ae69a36/tip.txt --------------------------------------------------------------------------------