从网上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
|
}
|
|