├── .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
--------------------------------------------------------------------------------