书圈|看完这篇还不懂高并发中的线程与线程池你来打我(内含20张图)( 五 )


while(true){structtask=GetFromQueue;//从队列中取出数据task->handle(task->data);//处理数据}以上就是线程池最核心的部分 。
理解这些你就能明白线程池是如何工作的了 。
线程池中线程的数量
现在线程池有了 , 那么线程池中线程的数量该是多少呢?
在接着往下看前先自己想一想这个问题 。
如果你能看到这里说明还没有睡着 。
要知道线程池的线程过少就不能充分利用CPU , 线程创建的过多反而会造成系统性能下降 , 内存占用过多 , 线程切换造成的消耗等等 。 因此线程的数量既不能太多也不能太少 , 那到底该是多少呢?
回答这个问题 , 你需要知道线程池处理的任务有哪几类 , 有的同学可能会说你不是说有两类吗?长任务和短任务 , 这个是从生命周期的角度来看的 , 那么从处理任务所需要的资源角度看也有两种类型 , 这就是没事儿找抽型和 。。 啊不 , 是CPU密集型和I/O密集型 。
1 , CPU密集型
所谓CPU密集型就是说处理任务不需要依赖外部I/O , 比如科学计算、矩阵运算等等 。 在这种情况下只要线程的数量和核数基本相同就可以充分利用CPU资源 。
书圈|看完这篇还不懂高并发中的线程与线程池你来打我(内含20张图)
文章图片
2 , I/O密集型
这一类任务可能计算部分所占用时间不多 , 大部分时间都用在了比如磁盘I/O、网络I/O等 。
书圈|看完这篇还不懂高并发中的线程与线程池你来打我(内含20张图)
文章图片
这种情况下就稍微复杂一些了 , 你需要利用性能测试工具评估出用在I/O等待上的时间 , 这里记为WT(waittime) , 以及CPU计算所需要的时间 , 这里记为CT(computingtime) , 那么对于一个N核的系统 , 合适的线程数大概是N*(1+WT/CT) , 假设I/O等待时间和计算时间相同 , 那么你大概需要2N个线程才能充分利用CPU资源 , 注意这只是一个理论值 , 具体设置多少需要根据真实的业务场景进行测试 。
当然充分利用CPU不是唯一需要考虑的点 , 随着线程数量的增多 , 内存占用、系统调度、打开的文件数量、打开的socker数量以及打开的数据库链接等等是都需要考虑的 。
因此这里没有万能公式 , 要具体情况具体分析 。
线程池不是万能的
线程池仅仅是多线程的一种使用形式 , 因此多线程面临的问题线程池同样不能避免 , 像死锁问题、racecondition问题等等 , 关于这一部分同样可以参考操作系统相关资料就能得到答案 , 所以基础很重要呀老铁们 。
线程池使用的最佳实践
线程池是程序员手中强大的武器 , 互联网公司的各个server上几乎都能见到线程池的身影 , 使用线程池前你需要考虑:
充分理解你的任务 , 是长任务还是短任务、是CPU密集型还是I/O密集型 , 如果两种都有 , 那么一种可能更好的办法是把这两类任务放到不同的线程池中 , 这样也许可以更好的确定线程数量如果线程池中的任务有I/O操作 , 那么务必对此任务设置超时 , 否则处理该任务的线程可能会一直阻塞下去线程池中的任务最好不要同步等待其它任务的结果总结
本节我们从CPU开始一路来到常用的线程池 , 从底层到上层、从硬件到软件 。 注意 , 这里通篇没有出现任何特定的编程语言 , 线程不是语言层面的概念(依然不考虑用户态线程) , 但是当你真正理解了线程后 , 相信你可以在任何一门语言下用好多线程 , 你需要理解的是道 , 此后才是术 。
希望这篇文章对大家理解线程以及线程池有所帮助 。
-END-
书圈|看完这篇还不懂高并发中的线程与线程池你来打我(内含20张图)
文章图片
【书圈|看完这篇还不懂高并发中的线程与线程池你来打我(内含20张图)】点击查看:【操作系统的教与学(教学大纲)】