//main.c文件
#include "test_pool.h"
#include <stdbool.h>
/*
通过线程池来调用下面这3个任务函数
*/
void *eat(void *arg)
{
printf("吃饭\n");
}
void *mysleep(void *arg)
{
printf("睡觉\n");
}
void *play(void *arg)
{
printf("打游戏\n");
}
int main(int argc,char **argv)
{
int num =5;
thread_pool *mypool = malloc(sizeof(struct pool));
//初始化线程池(3条线程)
init_pool(mypool,num);//在初始化的时候创建了num条线程
//添加了3个任务
add_task(mypool,eat,NULL);
add_task(mypool,mysleep,NULL);
add_task(mypool,play,NULL);
//按照实际情况来增加线程或者删除线程
//add_thread();
remove_thread(mypool,4);
//销毁线程池
destroy_pool(mypool);
return 0;
}
//线程池的函数
#include "test_pool.h"
/*
xxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxx
*/
//压栈的句柄函数
void handler(void *arg)
{
//解锁
thread_pool *pool = (thread_pool *)arg;
pthread_mutex_unlock(&pool->lock);
}
//做任务的线程--删除任务节点
void *routine(void *arg)
{
//1. 先接住线程池的地址
thread_pool *pool = (thread_pool *)arg;
struct task *p;
while(1)
{
//2. 线程取消例程函数
//将来要是有人要取消我,请先把锁解开,然后再响应取消。
pthread_cleanup_push(handler,(void *)&pool->lock);
//3. 上锁
pthread_mutex_lock(&pool->lock);
//如果当前线程池没有关闭,并且当前线程池没有任务做(有线程没有任务,池子是打开的)
while(pool->waiting_task == 0 && !pool->shutdown)
{
//那么就进去条件变量中睡觉。
pthread_cond_wait(&pool->cond, &pool->lock); //自动解锁
}
//要是线程池关闭了,或者有任务做,这些线程就会运行到这行代码
//判断当前线程池是不是关闭了,并且没有等待的任务
if(pool->waiting_task == 0 && pool->shutdown == true)
{
//如果线程池关闭,又没有任务做
//线程那么就会解锁
pthread_mutex_unlock(&pool->lock);
//线程走人
pthread_exit(NULL);
}
//能运行到这里,说明有任务做 (删除节点)
//p指向头节点的下一个
p = pool->task_list->next;
//让头节点的指针域指向p的下一个节点
pool->task_list->next = p->next;
//当前任务个数-1
pool->waiting_task--;
//解锁
pthread_mutex_unlock(&pool->lock);
//删除线程取消例程函数
pthread_cleanup_pop(0);
//设置线程不能响应取消
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
//执行这个p节点指向的节点的函数(执行任务)
(p->do_task)(p->arg); //等价跑了代码 eat(NULL)
//设置线程能响应取消
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
//释放p对应的空间
free(p);
}
pthread_exit(NULL);
}
//线程池的初始化
bool init_pool(thread_pool *mypool_head,int threads_number)
{
//初始化互斥锁
pthread_mutex_init(&mypool_head->lock,NULL);
//初始化条件变量
pthread_cond_init(&mypool_head->cond,NULL);
//初始化线程池开关量
mypool_head->shutdown = false;
//初始化线程池任务链表(单向链表)
//也就是初始化任务链表里面的链表头
mypool_head->task_list = malloc(sizeof(struct task));
//根据自定义的线程的数量创建线程
//使用for循环循环创建
mypool_head->tids = malloc(sizeof(pthread_t)*ACT_PTHREAD_ID);
if(mypool_head->task_list == NULL || mypool_head->tids == NULL)
{
perror("pthread_pool fail\n");
return false;
}
mypool_head ->task_list ->next= NULL;
mypool_head->max_waiting_task = MAX_PTHREAD_ID;
mypool_head->waiting_task = 0;
mypool_head->active_threads = threads_number;
int i;
for(i = 0;i < mypool_head->active_threads;i++)
{
if(pthread_create(&((mypool_head->tids)[i]),NULL,routine,(void *)mypool_head) != 0)
{
perror("create threads error");
return false;
}
}
//返回链表的开关量
return true;
}
//添加任务节点
bool add_task(thread_pool *pool,void *(*do_task)(void *arg), void *arg)
{
//新建任务链表的节点
struct task *new_task = malloc(sizeof(struct task));
new_task->do_task = do_task;
new_task->arg = arg;
new_task->next = NULL;
//上锁
pthread_mutex_lock(&pool->lock);
if(pool->waiting_task >= MAX_PTHREAD_ID)
{
//释放新节点
pthread_mutex_unlock(&pool->lock);
printf("too many task.\n");
free(new_task);
return false;
//解锁
}
struct task *tmp = pool->task_list;
while(tmp->next != NULL)
{
tmp = tmp->next;
}
tmp->next = new_task;
pool->waiting_task ++;
pthread_mutex_unlock(&pool->lock);
pthread_cond_signal(&pool->cond);
return true;
}
//添加线程
int add_thread(thread_pool *pool, unsigned additional_threads)
{
//如果添加的线程数为0
if(additional_threads == 0)
return 0;
unsigned total_threads = pool->active_threads + additional_threads;
int i,actual_increment = 0;
//创建线程
for(i=pool->active_threads; i < total_threads && i < MAX_PTHREAD_ID;i++)
{
if(pthread_create(&((pool->tids)[i]),NULL,routine,(void*)pool)!=0)
{
perror("add threads error");
if(actual_increment == 0)
return -1;
break;
}
actual_increment++;
}
pool->active_threads += actual_increment;
//返回实际的线程添加数
return actual_increment;
}
//删除线程
int remove_thread(thread_pool *pool, unsigned int removing_threads)
{
//如果删除的线程数为0
if(removing_threads == 0)
return pool->active_threads;
int i;
int errno;
//删除从最后面一个线程号开始删除
int remaining_threads = pool->active_threads - removing_threads;
remaining_threads = remaining_threads > 0 ? remaining_threads : 1;
for(i=pool->active_threads-1; i>remaining_threads-1; i--)
{
errno = pthread_cancel(pool->tids[i]); //取消这些线程
if(errno != 0)
break;
}
if(i == pool->active_threads-1) //删除失败
return -1;
else
{
pool->active_threads = i+1; //当前实际线程个数
return i+1;
}
//返回还有多少个线程数
}
bool destroy_pool(thread_pool *pool)
{
//1. 设置线程池关闭标志为真
pool->shutdown = true;
int errno;
//广播
pthread_cond_broadcast(&pool->cond); //目的: 就是让线程退出!
//2. 接合所有的线程
int i;
for(i=0; i<pool->active_threads; i++)
{
errno = pthread_join(pool->tids[i], NULL); //阻塞等待所有的线程退出
if(errno != 0)
{
printf("join tids[%d] error: %s\n",
i, strerror(errno));
}
else
printf("[%u] is joined\n", (unsigned)pool->tids[i]);
}
//3. 释放一些空间
free(pool->task_list); //释放链表
free(pool->tids); //释放线程数
free(pool);//释放线程池
return true;
}
//头文件
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
//宏定义
#define MAX_PTHREAD_ID 1024
#define ACT_PTHREAD_ID 1024
//任务链表节点
struct task
{
void *(*do_task)(void *arg);
void *arg;
struct task *next;
};
//线程池的结构体
typedef struct pool
{
pthread_mutex_t lock;
pthread_cond_t cond;
bool shutdown;
struct task *task_list;
pthread_t *tids;
unsigned max_waiting_task;
unsigned waiting_task;
unsigned active_threads;
}thread_pool;
void handler(void *arg);
void *routine(void *arg);
bool init_pool(thread_pool *mypool_head,int threads_number);
bool add_task(thread_pool *pool,void *(*do_task)(void *arg), void *arg);
int add_thread(thread_pool *pool, unsigned additional_threads);
int remove_thread(thread_pool *pool, unsigned int removing_threads);
bool destroy_pool(thread_pool *pool);
void handler(void *arg);