2.4.4 Worker线程执行任务
在Worker类中的run方法调用了runWorker方法来执行任务 , runWorker方法的执行过程如下:
- while循环不断地通过getTask()方法获取任务 。
- getTask()方法从阻塞队列中取任务 。
- 如果线程池正在停止 , 那么要保证当前线程是中断状态 , 否则要保证当前线程不是中断状态 。
- 执行任务 。
- 如果getTask结果为null则跳出循环 , 执行processWorkerExit()方法 , 销毁线程 。

图11 执行任务流程
三、线程池在业务中的实践3.1 业务背景
在当今的互联网业界 , 为了最大程度利用CPU的多核性能 , 并行运算的能力是不可或缺的 。通过线程池管理线程获取并发性是一个非常基础的操作 , 让我们来看两个典型的使用线程池获取并发性的场景 。
场景1:快速响应用户请求
描述:用户发起的实时请求 , 服务追求响应时间 。比如说用户要查看一个商品的信息 , 那么我们需要将商品维度的一系列信息如商品的价格、优惠、库存、图片等等聚合起来 , 展示给用户 。
分析:从用户体验角度看 , 这个结果响应的越快越好 , 如果一个页面半天都刷不出 , 用户可能就放弃查看这个商品了 。而面向用户的功能聚合通常非常复杂 , 伴随着调用与调用之间的级联、多级级联等情况 , 业务开发同学往往会选择使用线程池这种简单的方式 , 将调用封装成任务并行的执行 , 缩短总体响应时间 。另外 , 使用线程池也是有考量的 , 这种场景最重要的就是获取最大的响应速度去满足用户 , 所以应该不设置队列去缓冲并发任务 , 调高corePoolSize和maxPoolSize去尽可能创造多的线程快速执行任务 。

图12 并行执行任务提升任务响应速度
场景2:快速处理批量任务
描述:离线的大量计算任务 , 需要快速执行 。比如说 , 统计某个报表 , 需要计算出全国各个门店中有哪些商品有某种属性 , 用于后续营销策略的分析 , 那么我们需要查询全国所有门店中的所有商品 , 并且记录具有某属性的商品 , 然后快速生成报表 。
分析:这种场景需要执行大量的任务 , 我们也会希望任务执行的越快越好 。这种情况下 , 也应该使用多线程策略 , 并行计算 。但与响应速度优先的场景区别在于 , 这类场景任务量巨大 , 并不需要瞬时的完成 , 而是关注如何使用有限的资源 , 尽可能在单位时间内处理更多的任务 , 也就是吞吐量优先的问题 。所以应该设置队列去缓冲并发任务 , 调整合适的corePoolSize去设置处理任务的线程数 。在这里 , 设置的线程数过多可能还会引发线程上下文切换频繁的问题 , 也会降低处理任务的速度 , 降低吞吐量 。

图13 并行执行任务提升批量任务执行速度
3.2 实际问题及方案思考
线程池使用面临的核心的问题在于:线程池的参数并不好配置 。一方面线程池的运行机制不是很好理解 , 配置合理需要强依赖开发人员的个人经验和知识;另一方面 , 线程池执行的情况和任务类型相关性较大 , IO密集型和CPU密集型的任务运行起来的情况差异非常大 , 这导致业界并没有一些成熟的经验策略帮助开发人员参考 。
推荐阅读
- cad卸载工具怎么用 cad卸载干净的教程
- qq营销工具源码 最有效推广的方式
- 目前三防手机哪个好 最好的三防手机品牌
- 哪些人不宜喝酒
- 艾灸真的可以治疗哮喘吗
- 面包硬的其他原因
- 钓鲈鱼的饵料比较好用的有哪些
- 黄皮果的食用方法
- 骨盆前倾该怎么练呢
- 骨盆前倾是怎么形成的呢
