线程池实现的必要性:
当需要的线程量比较大时,需要不断的创建和销毁线程,会使得时间浪费比较大。这个时候就要使用线程池来节约时间的开销,让程序运行更有效率。
想要实现线程池,最为重要的两点是要有一个链式队列进行任务的准备,还有有线程池的工作线程进行工程。下面是我学习过程中完成的线程池的实验:
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#define NUM 10
typedef struct task
{
void *(*fun)(void *arg);
void * arg;
struct task *next;
}listnode, * linklist;//链表的创建
typedef struct threadpool
{
pthread_mutex_t mutex;
pthread_cond_t cond;
linklist H;
pthread_t pid[NUM];
int busywork;
}threadpool;//线程池的结构体
threadpool *pool;
void *workplace(void *arg)
{
while(1)
{
pthread_mutex_lock(&pool->mutex);
pthread_cond_wait(&pool->cond, &pool->mutex);
linklist p=pool->H;
pool->H=pool->H->next;
pthread_mutex_unlock(&pool->mutex);
p->fun(p->arg);//在解锁后执行实验结果会不按顺序
pool->busywork--;
}
}
void reallywork(void *arg)
{
printf("finsh work : %d\n",(int )arg);
}
void add(void *arg)
{
linklist p;
pthread_mutex_lock(&pool->mutex);
while(pool->busywork>NUM)//while等待,因为任务太多,线程需要等待
{
pthread_mutex_unlock(&pool->mutex);
usleep(1000);
pthread_mutex_lock(&pool->mutex);
}
pthread_mutex_unlock(&pool->mutex);
pthread_mutex_lock(&pool->mutex);
linklist q;
q=pool->H;
if((p=(linklist)malloc(sizeof(listnode)))==NULL)
{
perror("p");
}
p->arg=arg;
p->next=NULL;
p->fun=reallywork;
if(pool->H==NULL)
{
pool->H=p;
}
else
{
while(q->next!=NULL)
{
q=q->next;
}
q->next=p;
}
pool->busywork++;
pthread_cond_signal(&pool->cond);
pthread_mutex_unlock(&pool->mutex);
}
void pool_init()
{
if((pool=malloc(sizeof(threadpool)))==NULL)
{
perror("pool");
pthread_mutex_init(&pool->mutex,NULL);
pthread_cond_init(&pool->cond,NULL);
}
for(int i=0;i<10;i++)
{
pthread_create(&pool->pid[i],NULL,workplace,NULL);
}
pool->busywork=0;
pool->H=NULL;
}
void delate()
{
linklist q;
while(pool->H)
{
q=pool->H;
free(q);
pool->H=pool->H->next;
}
pthread_mutex_destroy(&pool->mutex);
pthread_cond_destroy(&pool->cond);
free(pool);
}
int main()
{
pool_init();
sleep(5);
for(int i=0;i<20;i++)
{
add(i);
}
sleep(1);
delate();
return 0;
}
以下是运行结果:
因为运行的任务量比较多,而线程比较少,所以可能会出现不按顺序进行的情况、