从网上download一份实现线程池的代码,比较有代表性,特此贴出来。
1 数据结构
设计构思点:1任务由线程池中的任务链表维护,当需要向线程池中添加任务时,无论是否分配线程执行。换言之,只要调用接口函数,任务就交给了线程池,而且应用程序认为线程池肯定会执行的。2 线程池中的线程,有三种状态,空闲,运行,结束。一开始进入空闲状态,等待分配任务,如果超时,则退出结束状态,如果被激活,那么就进入运行状态,执行完任务链表中的任务后,就立即进入空闲状态,注意此处不会直接退出,只有超时等待后,认为目前已经有足够的线程服务所以才退出将自己交给线程池。3线程永远是取出first指向的任务执行,而线程池永远是向last所指向的插入任务。
|
1
|
typedef
struct condition
| |
2
|
{
| |
3
|
pthread_mutex_t pmutex;
| |
4
|
pthread_cond_t pcond;
| |
5
|
} condition_t;
| |
6
|
| |
7
|
// 任务结构体,将任务放入队列由线程池中的线程来执行
| |
8
|
typedef
struct task
| |
9
|
{
| |
10
|
void *(*run)(void *arg);
// 任务回调函数
| |
11
|
void *arg;
// 回调函数参数
| |
12
|
struct task *next;
| |
13
|
} task_t;
| |
14
|
| |
15
|
// 线程池结构体
| |
16
|
typedef
struct threadpool
| |
17
|
{
| |
18
|
condition_t ready;
//任务准备就绪或者线程池销毁通知
| |
19
|
task_t *first;
//任务队列头指针
| |
20
|
task_t *last;
//任务队列尾指针
| |
21
|
int counter;
//线程池中当前线程数
| |
22
|
int idle;
//线程池中当前正在等待任务的线程数
| |
23
|
int max_threads;
//线程池中最大允许的线程数
| |
24
|
int quit;
//销毁线程池的时候置1
| |
25
|
} threadpool_t;
|
|
2处理流程
|
1
|
void *thread_routine(void *arg)
| |
2
|
{
| |
3
|
struct timespec abstime;
| |
4
|
int timeout;
| |
5
|
printf("thread 0x%x is starting\n",
(int)pthread_self());
| |
6
|
threadpool_t *pool = (threadpool_t *)arg;
| |
7
|
while (1)
| |
8
|
{
| |
9
|
timeout =
0;
| |
10
|
condition_lock(&pool->ready);
| |
11
|
pool->idle++;
| |
12
|
//
等待队列有任务到来或者线程池销毁通知
| |
13
|
while (pool->first ==
NULL && !pool->quit)
| |
14
|
{
| |
15
|
printf("thread 0x%x is waiting\n",
(int)pthread_self());
| |
16
|
//condition_wait(&pool->ready);
| |
17
|
clock_gettime(CLOCK_REALTIME, &abstime);
| |
18
|
abstime.tv_sec +=
2;
| |
19
|
int status =
condition_timedwait(&pool->ready, &abstime);
| |
20
|
if (status == ETIMEDOUT)
| |
21
|
{
| |
22
|
printf("thread 0x%x is wait timed out\n",
(int)pthread_self());
| |
23
|
timeout =
1;
| |
24
|
break;
| |
25
|
}
| |
26
|
}
| |
27
|
| |
28
|
//
等待到条件,处于工作状态
| |
29
|
pool->idle--;
| |
30
|
| |
31
|
//
等待到任务
| |
32
|
if (pool->first !=
NULL)
| |
33
|
{
| |
34
|
// 从队头取出任务
| |
35
|
task_t *t = pool->first;
| |
36
|
pool->first = t->next;
| |
37
|
// 执行任务需要一定的时间,所以要先解锁,以便生产者进程
| |
38
|
// 能够往队列中添加任务,其它消费者线程能够进入等待任务
| |
39
|
condition_unlock(&pool->ready);
| |
40
|
t->run(t->arg);
| |
41
|
free(t);
| |
42
|
condition_lock(&pool->ready);
| |
43
|
}
| |
44
|
//
如果等待到线程池销毁通知,
且任务都执行完毕
| |
45
|
if (pool->quit && pool->first ==
NULL)
| |
46
|
{
| |
47
|
pool->counter--;
| |
48
|
if (pool->counter ==
0)
| |
49
|
condition_signal(&pool->ready);
| |
50
|
| |
51
|
condition_unlock(&pool->ready);
| |
52
|
// 跳出循环之前要记得解锁
| |
53
|
break;
| |
54
|
}
| |
55
|
| |
56
|
if (timeout && pool->first ==
NULL)
| |
57
|
{
| |
58
|
pool->counter--;
| |
59
|
condition_unlock(&pool->ready);
| |
60
|
// 跳出循环之前要记得解锁
| |
61
|
break;
| |
62
|
}
| |
63
|
condition_unlock(&pool->ready);
| |
64
|
}
| |
65
|
| |
66
|
printf("thread 0x%x is exting\n",
(int)pthread_self());
| |
67
|
return
NULL;
| |
68
|
| |
69
|
}
| |
70
|
| |
71
|
// 初始化线程池
| |
72
|
void
threadpool_init(threadpool_t *pool,
int threads)
| |
73
|
{
| |
74
|
//
对线程池中的各个字段初始化
| |
75
|
condition_init(&pool->ready);
| |
76
|
pool->first =
NULL;
| |
77
|
pool->last =
NULL;
| |
78
|
pool->counter =
0;
| |
79
|
pool->idle =
0;
| |
80
|
pool->max_threads = threads;
| |
81
|
pool->quit =
0;
| |
82
|
}
| |
83
|
| |
84
|
// 往线程池中添加任务
| |
85
|
void
threadpool_add_task(threadpool_t *pool,
void *(*run)(void *arg), void *arg)
| |
86
|
{
| |
87
|
//
生成新任务
| |
88
|
task_t *newtask = (task_t *)malloc(sizeof(task_t));
| |
89
|
newtask->run = run;
| |
90
|
newtask->arg = arg;
| |
91
|
newtask->next =
NULL;
| |
92
|
| |
93
|
condition_lock(&pool->ready);
| |
94
|
//
将任务添加到队列
| |
95
|
if (pool->first ==
NULL)
| |
96
|
pool->first = newtask;
| |
97
|
else
| |
98
|
pool->last->next = newtask;
| |
99
|
pool->last = newtask;
| |
100
|
| |
101
|
//
如果有等待线程,则唤醒其中一个
| |
102
|
if (pool->idle >
0)
| |
103
|
condition_signal(&pool->ready);
| |
104
|
else
if (pool->counter < pool->max_threads)
| |
105
|
{
| |
106
|
//
没有等待线程,并且当前线程数不超过最大线程数,则创建一个新线程
| |
107
|
pthread_t tid;
| |
108
|
pthread_create(&tid,
NULL, thread_routine, pool);
| |
109
|
pool->counter++;
| |
110
|
}
| |
111
|
condition_unlock(&pool->ready);
| |
112
|
}
| |
113
|
| |
114
|
// 销毁线程池
| |
115
|
void
threadpool_destroy(threadpool_t *pool)
| |
116
|
{
| |
117
|
if (pool->quit)
| |
118
|
{
| |
119
|
return;
| |
120
|
}
| |
121
|
condition_lock(&pool->ready);
| |
122
|
pool->quit =
1;
| |
123
|
if (pool->counter >
0)
| |
124
|
{
| |
125
|
if (pool->idle >
0)
| |
126
|
condition_broadcast(&pool->ready);
| |
127
|
//
处于执行任务状态中的线程,不会收到广播
| |
128
|
//
线程池需要等待执行任务状态中的线程全部退出
| |
129
|
while (pool->counter >
0)
| |
130
|
condition_wait(&pool->ready);
| |
131
|
}
| |
132
|
condition_unlock(&pool->ready);
| |
133
|
condition_destroy(&pool->ready);
| |
134
|
}
|
|