/* 標頭檔:threadpool.h*/
#ifndef _TP_H_INCLUDED_
#define _TP_H_INCLUDED_
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <assert.h>
typedef struct worker {
void * (*process) (void *arg);
void *arg;
struct worker *next;
} threadpool_item_t;
typedef struct {
pthread_mutex_t queue_lock;
pthread_cond_t queue_ready;
threadpool_item_t *queue_head;
int shutdown; /*是否銷毀線程池*/
pthread_t *threadid;
int max_thread_num;/*線程池中允許的活動線程數目*/
int cur_queue_size; /*當前等待隊列的任務數目*/
} threadpool_t;
void pool_init (int max_thread_num);
int pool_destroy ();
int pool_add_worker (void * (*process) (void *arg), void *arg);
static void * thread_routine (void *arg);
#endif
/*具體實現:threadpool.c*/
#include "threadpool.h"
static threadpool_t *pool = NULL;
/*初始化線程池*/
void pool_init (int max_thread_num) {
pool = (threadpool_t *) malloc (sizeof (threadpool_t));
pthread_mutex_init (&(pool->queue_lock), NULL);
pthread_cond_init (&(pool->queue_ready), NULL);
pool->queue_head = NULL;
pool->max_thread_num = max_thread_num;
pool->cur_queue_size = 0;
pool->shutdown = 0;
pool->threadid = (pthread_t *) malloc (max_thread_num * sizeof (pthread_t));
int i;
for (i = 0; i < max_thread_num; i++) {
pthread_create (&(pool->threadid[i]), NULL, thread_routine, NULL);
}
}
/*向線程池中加入任務*/
int pool_add_worker (void *(*process) (void *arg), void *arg) {
/*構造一個新任務*/
threadpool_item_t *newworker = (threadpool_item_t *) malloc (sizeof (threadpool_item_t));
newworker->process = process;
newworker->arg = arg;
newworker->next = NULL;
pthread_mutex_lock (&(pool->queue_lock));
/*將任務加入到等待隊列中*/
threadpool_item_t *member = pool->queue_head;
if (member != NULL) {
while (member->next != NULL) member = member->next;
member->next = newworker;
} else{
pool->queue_head = newworker;
}
assert (pool->queue_head != NULL);
pool->cur_queue_size++;
pthread_mutex_unlock (&(pool->queue_lock));
/*喚醒一個等待線程*/
pthread_cond_signal (&(pool->queue_ready));
return 0;
}
/*銷毀線程池,等待隊列中的任務不會再被執行,但是正在啟動並執行線程會一直把任務運行完後再退出*/
int pool_destroy () {
if (pool->shutdown) return -1;/*防止兩次調用*/
pool->shutdown = 1;
/*喚醒所有等待線程,線程池要銷毀了*/
pthread_cond_broadcast (&(pool->queue_ready));
/*阻塞等待線程退出,否則就成殭屍了*/
int i;
for (i = 0; i < pool->max_thread_num; i++) {
pthread_join (pool->threadid[i], NULL);
}
free (pool->threadid);
/*銷毀等待隊列*/
threadpool_item_t *head = NULL;
while (pool->queue_head != NULL)
{
head = pool->queue_head;
pool->queue_head = pool->queue_head->next;
free (head);
}
/*銷毀條件變數和互斥量*/
pthread_mutex_destroy(&(pool->queue_lock));
pthread_cond_destroy(&(pool->queue_ready));
free (pool);
pool=NULL;
return 0;
}
/*線程主函數*/
static void * thread_routine (void *arg) {
printf ("starting thread %lu\n", pthread_self ());
while (1) {
pthread_mutex_lock (&(pool->queue_lock));
/*如果等待隊列為0並且不銷毀線程池,則處於阻塞狀態;*/
while (pool->cur_queue_size == 0 && !pool->shutdown)
{
printf ("thread %lu is waiting\n", pthread_self ());
pthread_cond_wait (&(pool->queue_ready), &(pool->queue_lock));
}
/*線程池要銷毀了*/
if (pool->shutdown) {
/*遇到break,continue,return等跳躍陳述式,千萬不要忘記先解鎖*/
pthread_mutex_unlock (&(pool->queue_lock));
printf ("thread %lu will exit\n", pthread_self ());
pthread_exit (NULL);
}
printf ("thread %lu is starting to work\n", pthread_self ());
assert (pool->cur_queue_size != 0);
assert (pool->queue_head != NULL);
/*隊列長度減去1,並取出鏈表中的頭元素*/
pool->cur_queue_size--;
threadpool_item_t *worker = pool->queue_head;
pool->queue_head = worker->next;
pthread_mutex_unlock (&(pool->queue_lock)); //解鎖
/*調用回呼函數,執行任務*/
(*(worker->process)) (worker->arg);
free (worker);
worker = NULL;
}
}
/* 下面是測試代碼 */
void * myprocess (void *arg)
{
printf ("threadid is 0x%x, working on task %d\n", pthread_self (),*(int *) arg);
sleep (1);/*休息一秒,延長任務的執行時間*/
return NULL;
}
int main (int argc, char **argv)
{
pool_init (3);/*線程池中最多三個活動線程*/
/*連續向池中投入10個任務*/
int *workingnum = (int *) malloc (sizeof (int) * 10);
int i;
for (i = 0; i < 10; i++)
{
workingnum[i] = i;
pool_add_worker (myprocess, &workingnum[i]);
}
/*等待所有任務完成*/ sleep (5);
/*銷毀線程池*/ pool_destroy ();
free(workingnum);
workingnum = NULL;
return 0;
}
編譯,運行:
$ gcc -std=c99 -o threadpool threadpool.h threadpool.c -lpthread
$ ./threadpool
starting thread 1115277632
thread 1115277632 is starting to work
threadid is 1115277632, working on task 0
starting thread 1125767488
thread 1125767488 is starting to work
threadid is 1125767488, working on task 1
starting thread 1136257344
thread 1136257344 is starting to work
threadid is 1136257344, working on task 2
thread 1115277632 is starting to work
threadid is 1115277632, working on task 3
thread 1125767488 is starting to work
threadid is 1125767488, working on task 4
thread 1136257344 is starting to work
threadid is 1136257344, working on task 5
thread 1115277632 is starting to work
threadid is 1115277632, working on task 6
thread 1125767488 is starting to work
threadid is 1125767488, working on task 7
thread 1136257344 is starting to work
threadid is 1136257344, working on task 8
thread 1115277632 is starting to work
threadid is 1115277632, working on task 9
thread 1125767488 is waiting
thread 1136257344 is waiting
thread 1115277632 is waiting
thread 1125767488 will exit
thread 1136257344 will exit
thread 1115277632 will exit