一个简单线程池的实现---需进一步完善
1.定义一个任务结构体,和一个线程池结构体
struct task{
void *(*p)(void*);//需要实现的函数;
void *arg;//函数所带的参数
struct task *next;
};
struct pthread_pool{
pthread_mutex_t mutex;//线程锁
pthread_cond_t cond;//条件变量
pthread_t *tids;//线程id
int thread_nums;//需创建的线程的数量
struct task *head;任务头结点
int cur_queue_size;//标记为控制条件变量的阻塞wait
};
2.添加任务----》初始化任务链表,添加节点
pool_add_task(void*(*pro)(void *),void *arg)
{
struct task *new = malloc(sizeof(struct task));//初始化任务结构体
new->p = pro;
new->arg = arg;
new->next = NULL;
pthread_mutex_lock(&(pool->mutex));//对公共资源操作时,记住时常上锁,解锁
struct task *lastnode = pool->head;
if(lastnode == NULL)//两种情况,判断头结点是否为空
{
pool->head = new;
}
//?????前面几句如果改成lastnode = new;出现段错误。原因:任务链表是struct pthread_pool的一个成员,而pool->head是任务链表的头。struct task *lastnode = pool->head;
else
{
while(lastnode->next!=NULL)//头结点不为空的情况
{
lastnode = lastnode->next;
}
lastnode->next = new;
}
pool->cur_queue_size++;//每添加一个结点,标记位+1
// printf("%d\n",*(int *)(new->arg));
// printf("%d\n",pool->cur_queue_size);
pthread_mutex_unlock(&(pool->mutex));
pthread_cond_signal(&pool->cond);//向处于阻塞状态的线程发送唤醒信号
}
3.线程初始化----》创建线程(功能函数)
void pool_init(int thread_num)
{
//对线程池结构体初始化
pool = malloc(sizeof(struct pthread_pool));
pthread_mutex_init(&(pool->mutex),NULL);
pthread_cond_init(&(pool->cond),NULL);
pool->thread_nums = thread_num;
pool->head = NULL;
pool->cur_queue_size = 0;
pool->tids = malloc(thread_num*sizeof(pthread_t));
int i = 0;
for(i=0;i<thread_num;i++)
{
pthread_create(&(pool->tids[i]),NULL,thread_r,NULL);
// printf("pool init\n");
}
}
4.任务函数(从任务链表的头部扣下结点,执行结构体中的函数)
void* thread_r(void*p)
{
while(1)
{
pthread_mutex_lock(&(pool->mutex));
while(pool->cur_queue_size == 0)
// printf("wait\n"); //ok
pthread_cond_wait(&(pool->cond),&(pool->mutex));
// printf("wait!\n");
struct task *q = pool->head;
// printf("q jiedian\n");
pool->head = q->next;
// printf("pool->next\n");
q->next = NULL;
// printf("put in error\n");
pool->cur_queue_size--;
pthread_mutex_unlock(&pool->mutex);
// printf("pthred_r\n");
(*(q->p))(q->arg);//执行结构体中的函数
free(q);
q = NULL;
// if(pool->cur_queue_size ==0)
// break;
}
}
5.功能函数中的函数指针。
void *f1(void *arg)
{
int a = *(int*)arg;
// sleep(1);
printf("%d\n",a);
}
main函数:(如何销毁线程池,需待解)
int main()
{
pool_init(3);
// printf("pthread pool is start\n");
// sleep(1);
int a=12;
pool_add_task(f1,(void*)&a);
// sleep(2);
// printf("pool_add_task\n");
pool_add_task(f1,(void*)&a);
pool_add_task(f1,(void*)&a);
// sleep(5);
pthread_join(pool->tids[0],NULL);
pthread_join(pool->tids[1],NULL);
pthread_join(pool->tids[2],NULL);
}