首先先明确一下线程池的主要作用是什么 线程池解决的核心问题就是资源管理问题。在并发环境下,系统不能够确定在任意时刻中,有多少任务需要执行,有多少资源需要投入。这种不确定性将带来以下若干问题:
我们如果使用Java语言的话,我们来分析一下Java线程池。
线程池的目的我们也知道了,大概设置的基础理论也清楚了。看看美团技术团队给的两个场景。
描述:用户发起的实时请求,服务追求响应时间。比如说用户要查看一个商品的信息,那么我们需要将商品维度的一系列信息如商品的价格、优惠、库存、图片等等聚合起来,展示给用户。
分析:从用户体验角度看,这个结果响应的越快越好,如果一个页面半天都刷不出,用户可能就放弃查看这个商品了。而面向用户的功能聚合通常非常复杂,伴随着调用与调用之间的级联、多级级联等情况,业务开发同学往往会选择使用线程池这种简单的方式,将调用封装成任务并行的执行,缩短总体响应时间。另外,使用线程池也是有考量的,这种场景最重要的就是获取最大的响应速度去满足用户,所以应该不设置队列去缓冲并发任务,调高corePoolSize和maxPoolSize去尽可能创造多的线程快速执行任务。
总结:将核心线程数和最大线程数设置到最大。这里的最大也就是我们在不影响其他接口或业务的情况下,还有就是机器资源OK的情况下。现在我们的机器都是分布式,在CPU或内存超过某一个阀值的时候就会自动扩容弹机器。还有就是队列的使用,也就是看你用户的峰值会有多少,设置一个有界队列当突然流量,比如100个同时请求,这个时候我们的系统最大承受能力是80个线程数,哪我们就设置个核心线程数设置的是20个,那么我们就搞100。个大小容量的队列。然后避过这个高峰我们的线程继续去消费。但是在我们目前这种场景是不设置队列的。设置位0,因为用户对等待是零容忍的。
描述:离线的大量计算任务,需要快速执行。比如说,统计某个报表,需要计算出全国各个门店中有哪些商品有某种属性,用于后续营销策略的分析,那么我们需要查询全国所有门店中的所有商品,并且记录具有某属性的商品,然后快速生成报表。
分析:这种场景需要执行大量的任务,我们也会希望任务执行的越快越好。这种情况下,也应该使用多线程策略,并行计算。但与响应速度优先的场景区别在于,这类场景任务量巨大,并不需要瞬时的完成,而是关注如何使用有限的资源,尽可能在单位时间内处理更多的任务,也就是吞吐量优先的问题。所以应该设置队列去缓冲并发任务,调整合适的corePoolSize去设置处理任务的线程数。在这里,设置的线程数过多可能还会引发线程上下文切换频繁的问题,也会降低处理任务的速度,降低吞吐量。
总结:这里的话我们会看到这个是一个稳定的请求过程,不会出现突然的猛增等情况,所以我个人认为在机器资源充分的情况下可以不设置队列,但是就如上文所说,尽量多的并发充分利用资源,所以说这里的话可以使用队列做一个临时缓冲做准备的地方,那我的理解就是,机器资源只有那么多设置的核心线程数和最大线程数不能满足这些大量的请求,但是我又不想让这些请求被拒绝,所以我开个缓冲队列来进行缓冲消费。