美文网首页JavaKNOWJava
线程池的几个灵魂拷问(二)

线程池的几个灵魂拷问(二)

作者: 千淘萬漉 | 来源:发表于2020-10-08 09:25 被阅读0次

线程池虽然在并发编程里很强大,但线程池使用面临的核心的问题在于:线程池的参数并不好配置。一方面线程池的运行机制不是很好理解,配置合理需要强依赖开发人员的个人经验和知识;另一方面,线程池执行的情况和任务类型相关性较大,IO密集型和CPU密集型的任务运行起来的情况差异非常大,这导致业界并没有一些成熟的经验策略帮助开发人员参考。

美团方案

比如网上流传的比较多的一个策略:

  • 如果是CPU密集型任务,就需要尽量压榨CPU,参考值可以设为 N(CPU)+1(比如是4核心 就配置为5)
  • 如果是IO密集型任务,参考值可以设置为2*N(CPU)

CPU密集型的为什么要+1呢?《Java并发编程实战》给出的原因是:即使当计算(CPU)密集型的线程偶尔由于页缺失故障或者其他原因而暂停时,这个“额外”的线程也能确保 CPU 的时钟周期不会被浪费。

这里先来看看美团帮我们总结的现在业界的一些线程池调参方案:

cpu参数方案

第一套方案是并发编程实战给出的,明显太理论化了,和实际业务想去甚远!

N(threads) = N(Cpu个数)*U(cpu的使用率)*(1+ 等待时间/计算时间)

第二套方案就没有考虑多个业务线程池的情况。
第三套方案的用到了TPS来参与计算,但是这也是流量恒定情况下算出来的,真实情况往往比较随机。

有啥比较好的办法吗?——那就是:线程池参数动态化,采用这种方案最好就是用这么一个办法来做:

  • 简化线程池配置:线程池构造参数有8个,但是最核心的是3个:corePoolSize、maximumPoolSize,workQueue,它们最大程度地决定了线程池的任务分配和线程分配策略
  • 参数可动态修改:为了解决参数不好配,修改参数成本高等问题
  • 加线程池监控

为什么能做到动态修改线程池参数呢?这是因为JDK本身就提供api方法支持动态的修改:

设置核心线程数的大小

至于如何在运行时状态实时查看,这里也有一个办法:用户基于JDK原生线程池ThreadPoolExecutor提供的几个public的getter方法,可以读取到当前线程池的运行状态以及参数:

线程池的运行时状态

用户基于这个功能可以了解线程池的实时状态,比如当前有多少个工作线程,执行了多少个任务,队列中等待的任务数等等。

Netty进阶指南给出来的方案

在Netty服务编写的过程中,也要涉及到两个线程池的参数配置,尤其是IO线程池的配置,这里书中也给了一套经验方案来针对线程的监控情况,可以参考:
同样的先用CPU核数*2,看看是否存在瓶颈,运行时的监控则用比较土的办法了:

  • 打印thread dump,同时获取当时cpu排在前面几个的线程号
  • 然后在线程dump文件中去对应的线程号堆栈
  • 然后在堆栈中查找是否有SelectotImpl.lookAndDoSelect处的lock信息

如果多次采集都发现有这堆信息的话,说明此时此刻的IO线程比较空闲,无需调整;但是如果一直在read或者write的执行处,则说明IO较为繁忙,可以适当的去调大NioEventLoop线程的个数来提升网络的读写性能。但是这边线程数的改动就不是动态化的了,服务启动后指定的线程数就不能再修改了。

参考文章


1、Java线程池实现原理及其在美团业务中的实践
2、微信文章:如何设置线程池参数?美团给出了一个让面试官虎躯一震的回答。

相关文章

  • 线程池的几个灵魂拷问(二)

    线程池虽然在并发编程里很强大,但线程池使用面临的核心的问题在于:线程池的参数并不好配置。一方面线程池的运行机制不是...

  • 线程池的几个灵魂拷问(一)

    之前的博客里有写过一点线程池,但是只是蜻蜓点水式的谈了一下,恰巧前段时间在工作中有了线程池的使用经验,而且线程池的...

  • Mysql的几个灵魂拷问(二)

    今天这篇主要是针对索引,开篇前先对Mysql数据库的性能有个整体的认识,一般来讲8c16g的数据库qps在1000...

  • java基础-多线程

    java线程池的实现 ThreadPoolExecutor java线程池几个参数 corePoolSize当线程...

  • 线程池的内部实现

    核心线程池的内部实现 对于核心的几个线程池,newFixedThreadPool、newSingleThreadE...

  • J.U.C——线程池专题

    主要讨论以下问题: 认识Java线程池 线程池的种类,区别,和使用场景 线程池的工作流程 线程池几个参数的理解 分...

  • AQS的几个灵魂拷问

    java并发包下很多API都是基于AQS来实现的加锁和释放锁等功能的,比如ReentrantLock、Reentr...

  • volatile的几个灵魂拷问

    要想讲清楚volatile关键字,这时候就应该主动从内存模型开始讲起,然后说原子性、可见性、有序性的理解,铺垫好这...

  • HashMap的几个灵魂拷问

    之前是写过一篇HashMap的原理文章的,比较基础 java基础之数据结构3(Map篇)[https://www...

  • Synchronized的几个灵魂拷问

    一、synchronized的简单介绍 关键字 synchronized可以保证在同一个时刻,只有一个线程可以执行...

网友评论

    本文标题:线程池的几个灵魂拷问(二)

    本文链接:https://www.haomeiwen.com/subject/zcunuktx.html