前言
没有基于业务场景,直接抛出这个问题,等同于耍流氓。
八股文告诉我们CPU密集型就核心数+1,IO密集型就核心数*2,那么真实业务中该怎么去配置呢。
方法论还是有的
1.需要分析线程池执行的任务的特性: CPU 密集型还是 IO 密集型
2.每个任务执行的平均时长大概是多少,这个任务的执行时长可能还跟任务处理逻辑是否涉及到网络传输以及底层系统资源依赖有关系
如果是 CPU 密集型,主要是执行计算任务,响应时间很快,cpu 一直在运行,这种任务 cpu的利用率很高,那么线程数的配置应该根据 CPU 核心数来决定,CPU 核心数=最大同时执行线程数,加入 CPU 核心数为 4,那么服务器最多能同时执行 4 个线程。过多的线程会导致上下文切换反而使得效率降低。那线程池的最大线程数可以配置为 cpu 核心数+1 如果是 IO 密集型,主要是进行 IO 操作,执行 IO 操作的时间较长,这是 cpu 出于空闲状态,导致 cpu 的利用率不高,这种情况下可以增加线程池的大小。这种情况下可以结合线程的等待时长来做判断,等待时间越高,那么线程数也相对越多。一般可以配置 cpu 核心数的 2 倍。
一个公式:线程池设定最佳线程数目 = ((线程池设定的线程等待时间+线程 CPU 时间)/
线程 CPU 时间 )* CPU 数目
这个公式的线程 cpu 时间是预估的程序单个线程在 cpu 上运行的时间(通常使用 loadrunner测试大量运行次数求出平均值)
日常业务线程池的配置,项目中比比皆是,线程池的参数设置大多基于开发任务人员的经验,基于对项目的熟悉,基于对屎山了如执掌。
假如啊一个新瓜蛋子刚来项目,接到要给业务人员发通知邮件,小同志很有想法,邮件嘛,异步发,搞个线程池,还不影响业务,咔咔一顿开发,参数就按照网上通用的来,IO密集型,核心线程数就CPU核心数*2吧。
老油条一看你这可不太行,这邮件本身也不重要,你搞这么多线程数很容易影响核心业务,
随手就从屎山的角落掏出一堆线程池告诉你,现在这个屎山可不稳定,回头项目上线一爆炸,很容易大家都一身屎,天天开发shift也不用按了,先把shit清了再说。
像这种边缘业务场景,核心线程数及最大线程数设置为1个就行了,队列大小嘛,按照现在业务量来说设置个1000个,满满的够了。
基于业务场景设置线程池参数,开发人员必须对业务和项目足够深度的了解,很深的那种,至少要到业务一加需求,有底气摇头say no。
但是,但是,但是,在复杂的业务场景下,我们总能找到一些规律,线程池这个不安分的炸弹也会被我们揪到一些蛛丝马迹。
我举个例子。
例子一
我们的职位详情页展示数据来源较多,涉及多方的业务,比如职位信息,企业信息,HR信息,还有风险提示等等
职位详情页是我们兼职服务的一个核心业务功能点,如果串行处理,在业务高峰期很容易响应过慢。
这个时候我们需要使用多线程的查询组装页面信息,线程池无疑是一个不二的选择。
首先这是个IO密集型业务,没有复杂的计算逻辑,对于参数设置,开始我们配置核心线程数50,最大线程数都是100个,阻塞队列1000,拒绝策略执行后降级处理。
核心线程数及最大线程数尽可能的大,防止详情页挂掉,正常请求耗时很少,线程数足够的话,业务高峰也不会有问题。
例子二
我们有个内部的业务系统,核心业务是使用Excel模板导入大量数据,然后标准化存储后,推送给第三方使用。
导入的业务数据需要层层清洗及计算,CPU密集型,这里我们线程池的配置就不能像上个例子那么配置了,选择较少的线程数,然后队列配置的大一些。
结语
有些我认为标准化的线程池配置,我列举出来,大家来找茬
- 自定义线程池
- 不适用吴姐队列队列
- 选用合适的拒绝策略