学习的途径以及我的大部分代码(甚至可以说全部,就改了很少)都来自于linya大佬的web-server项目
地址:https://github.com/linyacool/WebServer
目的
- 在多线程的应用中,线程的频繁创建与销毁会浪费时间,从而影响效率。所以引进线程池的概念,将多个线程维护在线程池中,就避免了线程频繁创建与开销的问题。
内容
根据代码来看看一个线程池应该有哪些内容:
- 一个互斥锁
- 一个条件变量:用来配合互斥锁来避免死锁
- 线程数组
- 任务队列
- 线程数
- 任务数
- 头部元素/尾部元素
- 等待的任务数
- 关闭状态
- 已经启动的线程数
函数
要实现的线程池函数
- 线程池的创建函数
- 添加任务的函数
- 销毁线程池
- 释放线程池
- 为线程分配任务的一个调度函数
线程池的创建
步骤:
- 给线程池申请空间
- 初始化成员变量,为线程数组和任务队列申请空间,初始化锁
- 给线程数组创建进程
pthread_cond_init()
pthread_mutex_init()//互斥锁和条件变量的初始化函数,返回0即成功。
代码:
线程池添加任务
步骤:
- 拥有互斥锁
- 添加任务信息进任务队列队尾
- 移动队尾元素
- 使用条件变量唤醒线程
- 释放互斥锁
- 任务组成:一个指向函数的指针,一个void型指针
- 注意:添加任务时要用互斥锁锁住,防止线程此时进入。每添加完一个任务,用条件变量通知阻塞的线程,唤醒其使其工作。并在最后释放互斥锁
销毁线程池
- 不能直接全部释放线程池的原因:要将线程持有的资源全部回收,否则会一直占有。
释放线程池
- 把线程池中所有占用内存的元素要全部释放,包括线程,任务队列,锁。
线程调度
- 这里引入线程池关闭的两种情况:
- 立即关闭:线程池即时关闭,线程池中任务不再执行
- 优雅关闭:线程池不再接受新的任务,但是执行完线程池中剩余任务
- 线程分配任务时也要用互斥锁
测试
写了一个主函数,创建了一个线程池。并输出一个用const定义的一个线程数。
编写一个简单的Makefile即可
结果: