利特尔法则

利特尔法则派生于排队论,用以下数学公式表示:
L=λWL = λW L=λW
L 系统中存在的平均请求数量。

λ 请求有效到达速率。例如:5/s 表示每秒有5个请求到达系统。

W 请求在系统中的平均等待执行时间。

排队论:研究服务系统中排队现象随机规律的学科,探究排队有关的数量指标的概率规律性。

场景

我们先假设一个店铺员工调整场景。

前提

  • 每个客户一次只买一只炸鸡;

  • 每位员工制作一个炸鸡需要1分钟。

  • 客户买炸鸡时等待时间越短,体验越好。

如果你是一家炸鸡店老板,今年受疫情影响需要对店里的员工进行调整,你会如何处理?

这个问题本质就是员工利用率客户体验之间的权衡。

  1. 为了让客户保持极佳体验,需要保持员工数量或增加员工;

  2. 为避免资源浪费,控制人力成本,需要裁减空闲员工。

假设店里目前有3名员工。你如何进行员工调整决策。我们分析以下几种情形。

平均客流量 = 3人/分钟 客户等待时间稍短,体验良好,并且员工工作都是饱和。此时不需要调整。

平均客流量 < 3人/分钟 客户等待时间稍短,体验良好,但是始终有一个员工在打酱油,此时可以考虑减裁一人。

平均客流量 > 3人/分钟 客户5,6,7等待时间延长体验稍差,此时可以根据实际情况增加员工。

平均每分钟客流量 ≈ 员工数 为最佳。

线程池

其实线程池处理也算是一个排队模型。简化Java线程池处理模型如下:

线程池任务执行大致阶段:提交 --> 入队列或直接执行 —> 实际执行

  • 任务提交频率:每秒任务提交数;

  • 任务队列等待平均耗时:任务队列等待总耗时除以实际执行数;

  • 任务实际执行平均耗时:任务实际运行总耗时除以实际执行数;

  • 任务执行平均耗时:任务队列等待平均耗时加任务实际执行平均耗时;

我们可以根据以下指标来评估调整线程池参数

线程池中平均任务数 = 任务提交频率 * 任务执行平均耗时

线程等待耗时与响应时间比率 = 任务队列等待总耗时 / (任务队列等待总耗时 + 任务实际执行总耗时


线程等待耗时与响应时间比率 过高,说明任务排队较多,评估当前线程池大小是否合理,结合系统负载进行相应调整。

线程池中平均任务数 < 目前线程池大小 应适当减少线程数量。

系统平均处理任务数 > 目前线程池大小 在这种情况下,先评估当前系统是否有能力支撑更大的线程数量(如CPU数,内存等),然后再进行调整。

代码片段

@Slf4j
public class MonitoredThreadPoolExecutor extends ThreadPoolExecutor {//任务提交成功时间private final ConcurrentHashMap<Runnable, Long> timeOfRequest = new ConcurrentHashMap<>();//任务实际开始执行时间private final ThreadLocal<Long> startTime = new ThreadLocal<>();//上一个任务提交成功时间private long lastArrivalTime;// 任务实际执行总数private final AtomicInteger numberOfRequestsRetired = new AtomicInteger();// 任务提交总数private final AtomicInteger numberOfRequests = new AtomicInteger();// 任务实际执行总耗时private final AtomicLong totalServiceTime = new AtomicLong();// 任务在队列等待总耗private final AtomicLong totalPoolTime = new AtomicLong();// 新任务提交总耗时private final AtomicLong aggregateInterRequestArrivalTime = new AtomicLong();public MonitoredThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);}@Overrideprotected void beforeExecute(Thread worker, Runnable task) {super.beforeExecute(worker, task);startTime.set(System.nanoTime());}@Overrideprotected void afterExecute(Runnable task, Throwable t) {try {long start = startTime.get();totalServiceTime.addAndGet(System.nanoTime() - start);totalPoolTime.addAndGet(start - timeOfRequest.remove(task));numberOfRequestsRetired.incrementAndGet();} finally {if (null != t) {log.error(AppSystem.ERROR_LOG_PREFIX + "线程池处理异常:", Throwables.getRootCause(t));}super.afterExecute(task, t);}}@Overridepublic void execute(Runnable task) {long now = System.nanoTime();numberOfRequests.incrementAndGet();synchronized (this) {if (lastArrivalTime != 0L) {aggregateInterRequestArrivalTime.addAndGet(now - lastArrivalTime);}lastArrivalTime = now;timeOfRequest.put(task, now);}super.execute(task);}
}

测试

两组迭代请求,一次提交10个任务,线程数为1

两组迭代请求,一次提交10个任务,线程数为10

两组迭代请求,一次提交10个任务,线程数为50

上面测试比较片面。现实应根据系统长期平均指标进行调整。

总结

利特尔法则应用场景很多。欢迎大家留言交流!

如何用利特尔法则调整线程池大小相关推荐

  1. 线程池大小选择:针对 I/O 密集型场景和 CPU 密集型场景

    线程池大小选择:针对 I/O 密集型场景和 CPU 密集型场景 I/O 密集型场景 CPU密集型场景 线程池大小选择 线程池在 I/O 密集型场景的必要性 线程池在 CPU 密集型场景的必要性 线程池 ...

  2. java 利特尔法则_Java Web应用中调优线程池的重要性

    不论你是否关注,Java Web应用都或多或少的使用了线程池来处理请求.线程池的实现细节可能会被忽视,但是有关于线程池的使用和调优迟早是需要了解的.本文主要介绍Java线程池的使用和如何正确的配置线程 ...

  3. 动态调整线程池_调整线程池的重要性

    动态调整线程池 无论您是否知道,您的Java Web应用程序很可能都使用线程池来处理传入的请求. 这是许多人忽略的实现细节,但是迟早您需要了解如何使用该池以及如何为您的应用程序正确调整池. 本文旨在说 ...

  4. 基于 Nacos Config 事件监听 动态调整线程池参数

    一.Nacos Config 事件监听 在实际项目中一般都会使用线程池解决一些异步并发问题,不过线程池核心参数很大程度上一次性进行设置,但系统运行起来总有可能出现各种各样的问题,如果修改线程池的参数则 ...

  5. 动态调整线程池参数实践

    欢迎大家关注我的微信公众号[老周聊架构],Java后端主流技术栈的原理.源码分析.架构以及各种互联网高并发.高性能.高可用的解决方案. 一.线程池遇到的挑战 我们上一篇 <一文读懂线程池的实现原 ...

  6. idhttpserver是按线程接受请求的吗_1000个并发线程,10台机器,每台机器4核,设计线程池大小...

    一道面试题 兄弟们,怎么说? 我觉得如果你工作了两年左右的时间,或者是突击准备了面试,这题回答个八成上来,应该是手到擒来的事情.这题中规中矩,考点清晰,可以说的东西不是很多. 但是这都上血书了,那不得 ...

  7. 1000个并发线程,10台机器,每台机器4核,设计线程池大小

    这是why哥的第 71 篇原创文章 一道面试题 兄弟们,怎么说? 我觉得如果你工作了两年左右的时间,或者是突击准备了面试,这题回答个八成上来,应该是手到擒来的事情.这题中规中矩,考点清晰,可以说的东西 ...

  8. 别再纠结线程池大小/线程数量了,没有固定公式的

    可能很多人都看到过一个线程数设置的理论: CPU 密集型的程序 - 核心数 + 1 I/O 密集型的程序 - 核心数 * 2 不会吧,不会吧,真的有人按照这个理论规划线程数? 线程数和CPU利用率的小 ...

  9. 别再纠结线程池大小 + 线程数量了,没有固定公式的!

    来源:juejin.cn/post/6948034657321484318 线程数和CPU利用率的小测试 线程数和CPU利用率的小总结 线程数规划的公式 真实程序中的线程数 附录 Java 获取CPU ...

最新文章

  1. VC++ GetSafeHwnd()和GetSafeHandle()
  2. java线程-保护性暂停(wait,notify实现)
  3. (二十三)原型模式详解(clone方法源码的简单剖析)
  4. at指令 fpga_FPGA毕设系列 | 无线通信
  5. 使用Spring-AOP
  6. [python-图像处理]python图片处理技巧[基本操作]
  7. 配置Android Studio内置jre的环境变量
  8. java 抽象类 final_final/抽象类/interface
  9. 编程也讲禅,您读过《金刚经》吗?——ADO.NET核心类的灭度与SQLHelper的诞生——十八相送(上)...
  10. matlab 中ctf,CTF中常见的web
  11. 运动计步app开发的功能分析
  12. nofollow是什么意思,nofollow标签的作用是什么?
  13. XSS篇——javascript:伪协议
  14. 无线移动通信技术快速发展历程和趋向
  15. K8S集群节点显示NotReady怎么解决?
  16. MySQL求百分比带百分号%
  17. Nim博弈和威佐夫博弈 Return of the Nim
  18. vxWorks启动时间
  19. 中科柏诚与知名上市公司南天信息(000948)签署战略合作协议
  20. cad中直径符号不显示_怎么在CAD、Word里敲出直径符号,你会吗?

热门文章

  1. 《CSS揭秘》读后感
  2. oracle和mybatis自增,在Springboot项目中使用MybatisPlus和Oracle实现主键ID的自增
  3. 虚拟机安装系统的网络配置问题(Contos7版)
  4. 韩语计算机术语大全,韩语学习:韩语计算机、互联网术语 - 英语家园
  5. 基于Python实现的论坛帖子情感分析
  6. 【韩松】Deep Gradient Comression_一只神秘的大金毛_新浪博客
  7. python之Matplotlib
  8. 【机器学习实战】美国波斯顿房价预测
  9. 第二章 进程管理(3)——进程同步
  10. alpha在matlab中的作用,在MATLAB中用alpha值绘制圆圈