Linux 线程池源码分析
**
线 程 池
一、介绍线程池的文件
thread_pool.c --> 线程池源码,用户不需要修改,如果要使用线程池接口,只需要把这个文件一起编译就行。
thread_pool.h --> 线程池中结构体,函数声明,宏定义…
二、线程池实现过程。
1、什么是线程池?
线程池就是多个线程组合在一起的集合,就像一家公司一样,由多个员工组成的一个集合,
当有任务时,这些线程就会去处理任务,当没有任务时,线程就会休息。
2、如何描述一个线程池? -> 使用一个结构体来描述。
typedef struct thread_pool
{
pthread_mutex_t lock; ---> 互斥锁
pthread_cond_t cond; ---> 条件变量
bool shutdown; ---> 线程池状态 true->关闭 false->开启
struct task *task_list; ---> 任务队列头节点
pthread_t *tids; ---> 存储线程池中所有线程ID号空间的地址
unsigned max_waiting_tasks; ---> 线程池中最大等待的任务个数
unsigned waiting_tasks; ---> 线程池正在等待的任务个数
unsigned active_threads; ---> 当前线程池线程的个数
}thread_pool;
给struct thread_pool取了一个新的别名叫thread_pool。
不取别名,声明结构体变量和指针:
struct thread_pool pool;
struct thread_pool *pool;
取了别名之后,声明:
thread_pool pool;
thread_pool *pool;
//任务链表结构体的原型
struct task
{
void *(*do_task)(void *arg); ---> 任务执行函数
void *arg; ---> 参数
struct task *next; ---> 指针域,用于存放下一个任务的地址
};
三、线程池实现接口。
1、初始化线程池。
函数接口: bool init_pool(thread_pool *pool, unsigned int threads_number)c
pool: 线程池结构体的地址
threads_number: 初始化线程池条数。
返回值:
成功:true
失败:false
总结: 初始化线程池中一些变量以及申请空间、设置起始值。
2、投放任务到线程池中。
函数接口: bool add_task(thread_pool *pool,void *(*do_task)(void *arg), void *arg)
pool:线程池结构体的地址
do_task: 新任务的执行函数
arg: 传递给新任务执行函数的参数
返回值:
成功:true
失败:false
总结: 为新任务申请堆区空间,如果申请成功,就将该节点尾插到链表的末尾,
添加成功后,就随机唤醒一个线程来做这个任务。
3、分析线程的例程函数。
总结:如果线程池处于开启状态,并且没有任务做,那么线程就会睡眠,只要有任务做,
无论线程池是开启还是关闭,线程就会继续做任务,把头节点的下一个节点取出,
执行完任务函数之后,就继续下一个任务/睡眠。
4、添加线程。
函数接口: int add_thread(thread_pool *pool, unsigned additional_threads)
pool: 线程池结构体的地址
additional_threads: 添加线程的条数
返回值:
成功:实际创建的条数
失败:-1
总结: 往线程池中添加线程,如果大于20条,就会创建失败。
5、删除线程。
函数接口: int remove_thread(thread_pool *pool, unsigned int removing_threads)
pool: 线程池结构体的地址
removing_threads: 需要删除线程的条数
返回值:
成功:当前剩余的条数
失败:-1
总结: 删除0条,可以返回当前剩余的条数。
6、 销毁线程池。
函数接口: bool destroy_pool(thread_pool *pool)
pool:线程池结构体的地址
返回值:
成功:true
失败:false
总结: 设置标志位为true,然后唤醒所有线程起来退出,然后释放全部堆区空间。
四、线程池使用
总结 :如果我们需要使用线程池,不需要修改源码,
只需要知道如何调用init_pool()、add_task()、add_threads()、rmove_threads()
这些函数就足够,还有就是要自己写清楚任务函数是什么。
thread_pool.h
#ifndef _THREAD_POOL_H_
#define _THREAD_POOL_H_
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <pthread.h>
#define MAX_WAITING_TASKS 1000
#define MAX_ACTIVE_THREADS 20
struct task
{
void *(*do_task)(void *arg);
void *arg;
struct task *next;
};
typedef struct thread_pool
{
pthread_mutex_t lock;
pthread_cond_t cond;
bool shutdown;
struct task *task_list;
pthread_t *tids;
unsigned max_waiting_tasks;
unsigned waiting_tasks;
unsigned active_threads;
}thread_pool;
bool init_pool(thread_pool *pool, unsigned int threads_number);
bool add_task(thread_pool *pool, void *(*do_task)(void *arg), void *task);
int add_thread(thread_pool *pool, unsigned int additional_threads_number);
int remove_thread(thread_pool *pool, unsigned int removing_threads_number);
bool destroy_pool(thread_pool *pool);
void *routine(void *arg);
#endif