1. 多线程存在的问题
1、进程所支持的线程数量问题(受限)
2、线程的创建和销毁的开销问题
2. 线程池的概念
3. 创建线程池
要求:创建一个线程池和任务队列, 往任务队列中添加任务,线程池中线程的工作任务是输出"hello world!"、"welcome to China!"和一个传入的参数
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
struct job
{
void *((*func)(void *arg));
void *arg;
struct job *next;
};
struct threadpool
{
int thread_num;
pthread_t *pthread_ids;
struct job *head; //任务队列的头
struct job *tail; //任务队列的尾
int queue_max_num;
int queue_cur_num;
pthread_mutex_t mutex;
pthread_cond_t queue_empty;
pthread_cond_t queue_not_empty;
pthread_cond_t queue_not_full;
};
void *threadpool_function(void *arg)
{
struct threadpool *pool = (struct threadpool *)arg;
struct job *pjob = NULL;
while(1)
{
pthread_mutex_lock(&(pool->mutex));
while(pool->queue_cur_num == 0)
{
pthread_cond_wait(&(pool->queue_not_empty), &(pool->mutex));
}
pjob = pool->head;
pool->queue_cur_num--;
if(pool->queue_cur_num != pool->queue_max_num)
{
pthread_cond_broadcast(&(pool->queue_not_empty)); //唤醒条件变量
}
if(pool->queue_cur_num == 0)
{
pool->head = pool->tail = NULL;
}
else
{
pool->head = pool->head->next;
}
pthread_mutex_unlock(&(pool->mutex));
(*(pjob->func))(pjob->arg);
free(pjob);
pjob = NULL;
}
}
//线程池初始化函数
struct threadpool *threadpool_init(int thread_num, int queue_max_num)
{
struct threadpool *pool = (struct threadpool *)malloc(sizeof(struct threadpool));
//malloc
pool->queue_max_num = queue_max_num;
pool->queue_cur_num = 0;
pool->head = NULL;
pool->tail = NULL;
pthread_mutex_init(&(pool->mutex), NULL);
pthread_cond_init(&(pool->queue_empty), NULL);
pthread_cond_init(&(pool->queue_not_empty), NULL);
pthread_cond_init(&(pool->queue_not_full), NULL);
pool->thread_num = thread_num;
pool->pthread_ids = (pthread_t *)malloc(sizeof(pthread_t) *thread_num);
//malloc
for (int i = 0; i < pool->thread_num; i++)
{
pthread_create(&(pool->pthread_ids[i]), NULL, threadpool_function, (void *)pool);
}
return pool;
}
//往任务队列里添加任务的函数
void threadpool_add_job(struct threadpool *pool, void *(func)(void *), void *arg)
{
pthread_mutex_lock(&(pool->mutex));
//判断线程池是否为满
while(pool->queue_cur_num == pool->queue_max_num)
{
pthread_cond_wait((&pool->queue_not_full), &(pool->mutex)); //阻塞等待
}
struct job *pjob = (struct job *)malloc(sizeof(struct job));
//malloc
//任务队列参数初始化
pjob->func = func;
pjob->arg = arg;
pjob->next = NULL;
if(NULL == pool->head)
{
pool->head = pool->tail = pjob;
pthread_cond_broadcast(&(pool->queue_not_empty));
}
else
{
pool->tail->next = pjob;
pool->tail = pjob;
}
pool->queue_cur_num++;
printf("%d\n", pool->queue_cur_num);
pthread_mutex_unlock(&(pool->mutex));
}
void thread_destory(struct threadpool *pool)
{
pthread_mutex_lock(&(pool->mutex));
while(pool->queue_cur_num != 0)
{
pthread_cond_wait(&(pool->queue_empty), &(pool->mutex));
}
pthread_mutex_unlock(&(pool->mutex));
pthread_cond_broadcast(&(pool->queue_empty));
pthread_cond_broadcast(&(pool->queue_not_empty));
pthread_cond_broadcast(&(pool->queue_not_full));
free(pool->pthread_ids); //释放存放线程号的空间
for (int i = 0; i < pool->thread_num; i++)
{
pthread_cancel(pool->pthread_ids[i]);
pthread_join(pool->pthread_ids[i], NULL);
}
//释放任务队列
struct job *temp;
while(pool->head != NULL)
{
temp = pool->head;
pool->head = temp->next;
free(temp);
}
free(pool); //释放线程池
}
//任务的工作函数
void *work(void *arg)
{
char *p = (char *)arg;
printf("hello world! %s\n", p);
printf("welcome to China! %s\n", p);
sleep(1);
}
int main()
{
struct threadpool *pool = threadpool_init(10, 100); //线程池初始化
threadpool_add_job(pool, work, "1");
threadpool_add_job(pool, work, "2");
threadpool_add_job(pool, work, "3");
threadpool_add_job(pool, work, "4");
threadpool_add_job(pool, work, "5");
threadpool_add_job(pool, work, "6");
threadpool_add_job(pool, work, "7");
threadpool_add_job(pool, work, "8");
threadpool_add_job(pool, work, "9");
threadpool_add_job(pool, work, "10");
return 0;
}
运行结果如下:
创建的线程池存在的问题:
由于不知道有多少线程,所以初始化时容易创建过多的线程,造成资源浪费(解决方案:先设置一个阈值,当超过这个阈值就再创建一些线程;若不超过阈值,就不用再创建线程)。