线程池优化

admin / 开发 / ... / Reads: 748

Java 线程池

Java 线程池会生成一个队列,要执行的任务会被提交到这个队列中。有一定数量的线程会在队列中取任务,然后执行。

任务执行完毕以后,线程会返回任务队列,等待其他任务并执行。线程池中有一定数量的线程随时待命。

由于生成和维持这些线程是需要耗费资源了,维持太多或者太少的线程都会对系统运行效率造成影响,因此对线程池优化是有意义的。

在做线程池调优之前,先介绍一下线程的几个基本参数,以及线程池运行的原理:

  • corePoolSize,线程池的基本大小,无论是否有任务需要执行,线程池中线程的个数。只有在工作队列占满的情况下,才会创建超出这个数量的线程。

  • maximumPoolSize,线程池中允许存在的最大线程数。

  • poolSize,线程池中线程的数量。

当提交任务需要流程池处理时,会经过以下判断:

  • 线程池中的线程数还没有达到基本大小,也就是 poolSize

  • 线程池中的线程数大于或等于基本大小,也就是 poolSize>=corePoolSize,并且任务队列未满时,将任务提交到阻塞队列排队等候处理。

  • 如果当前线程池的线程数大于或等于基本大小,也就是 poolSize>=corePoolSize 且任务队列占满时,需要分两种情况考虑。

①当 poolSize<maximumPoolSize,新增线程来处理任务;②当 poolSize=maximumPoolSize,线程池的处理能力达到极限,因此拒绝新增加的任务。

线程池容量配置

从上面线程池原理可以看出,corePoolSize 设置是整个线程池中最关键的参数。

如果设置太小会导致线程池的吞吐量不足,因为新提交的任务需要排队或者被拒绝处理;设置太大可能会耗尽计算机的 CPU 和内存资源。

那么如何配置合理的线程池大小呢?如果将被处理的任务分为,CPU 密集型任务和 IO 密集型任务。前者需要更多 CPU 的运算操作,后者需要更多的 IO 操作。

CPU 密集型任务应配置尽可能小的线程,如配置 CPU 个数 +1 的线程数,IO 密集型任务应配置尽可能多的线程,因为 IO 操作不占用 CPU,不要让 CPU 闲下来,应加大线程数量,如配置两倍 CPU 个数 +1。

CPU 的数字是一个假设,实际环境中需要进行测试,这里给大家一个思路。

若任务对其他系统资源有依赖,如任务依赖数据库返回的结果(IO 操作)。其等待时间越长,CPU 空闲时间就越长,那么线程数量应该越大,才能更好的利用 CPU。

因此在 IO 优化中发现一个估算公式:

最佳线程数目=((线程等待时间+线程 CPU 时间)/线程 CPU 时间 )* CPU 数目。

将公式进一步化简,得到:

最佳线程数目= (线程等待时间与线程 CPU 时间之比+1)* CPU 数目。

因此得到结论:线程等待时间所占比例越高,需要越多线程。线程 CPU 时间所占比例越高,需要越少线程。

从另外一个角度验证上面对 IO 密集型(线程等待时间占比高)和 CPU 密集型(CPU 时间占比高)设置线程池大小的想法。

关于作者

王硕,网名信平,十年软件开发经验,业余产品经理,精通Java/Python/Go等,喜欢研究技术,著有《PyQt 5 快速开发与实战》《Python 3.* 全栈开发》,多个业余开源项目托管在GitHub上,欢迎微博交流。

Comments

Make a comment

Author: admin

Publish at: ...

关于作者

王硕,网名信平,十多年软件开发经验,业余架构师,熟悉 Java/Python/Go 等,喜欢读书,音乐和宅在家里。
专注于研究互联网产品和技术,提供中文精品教程。 本网站与其它任何公司及/或商标无任何形式关联或合作。
Email: xujieiata@163.com

www.ultrapower.com ,王硕的博客,专注于研究互联网产品和技术,提供中文精品教程。 本网站与其它任何公司及/或商标无任何形式关联或合作。