首页 > 数据库 > 数据库开发技术 > 如何用Java计算线程池的大小



“在 executor pool中使用多少个线程,22、50 或 10”——在创建线程池时多次问过类似的问题,我们需要选择池中的线程数。如果我们选择过多的线程,那么最终可能会耗尽资源、CPU、内存。如果我们选择的线程数量太少,那么系统的吞吐量就会很差,因为 CPU/内存没有得到足够的使用。
要为线程池选择正确的线程数,我们需要了解线程池将处理哪种类型的任务。
一般来说,所有可能的任务都可以分为两组:一般来说,所有可能的任务都可以分为两组:
compute-intensive tasks或CPU Bound tasks,I/O tasks或I/O Bound tasks
计算密集型任务通常是 CPU 不断加载工作并且 CPU 空闲时间与使用时间相比要短得多的任务。计算密集型任务通常是 CPU 不断加载工作并且 CPU 空闲时间与使用时间相比要短得多的任务。
CPU | C | W | C | W | C | W | C...|-----------|---|-----------|---|-----------|---|-------->
其中C- CPU 上的计算时间,W- CPU 的空闲时间,等待工作。
在计算密集型任务的情况下,系统通常通过以下公式计算的线程池大小来实现最佳利用率。
Threads count = N + 1
where N- 机器中的 CPU 内核数,可以在 Java 中使用
Runtime.getRuntime().availableProcessors()因此,如果一个系统有四个 CPU 内核,那么最佳的最大线程数应该是五个。
I/O 任务(I/O 绑定)
I/O 任务是涉及通过网络调用与另一台机器上的不同应用程序进行大量通信的任务。例如,当一个线程向远程系统运行 Http 请求或从数据库中获取数据时。I/O 任务的特点是处理时间短,空闲时间长——CPU 负载较少,线程等待从不同机器获取数据。
CPU | C | W | C | W | C | W | C...|---|-------|---|---|------|---|-------->Time
其中
C- CPU 上的计算时间,
W- CPU 的空闲时间,等待工作。
在I/O tasksI/O tasks的情况下
Threads count = N * U * (1 + W/C)其中
N- 机器中的 CPU 内核数,可以在 Java 中获得Runtime.getRuntime().availableProcessors()
U- 目标 CPU 利用率和 0 <= U<= 1
W/C- 等待时间 ( W) 与计算时间 ( C)的比率
让我们计算以下示例:
1.一个系统有四个 CPU 内核,所以N= 4;
2.我们的目标是 100% CPU 利用率,所以U= 1;
3.我们可以粗略估计一个请求的等待时间为 100ms ( W),实际计算时间约为 20ms ( C)。
那么我们应该期望线程数应该20
为4 * 1 * 100/20 = 20.
结论
本文概括地描述了如何计算最佳线程池大小的想法。线程池大小可能会比公式计算的更大。很多方面都会影响线程池的大小,比如其他应用程序是否在同一台机器上工作,以及这些应用程序消耗了多少 CPU 时间。
我要强调的是,公式给了我们一个线程池的估计大小,应该在测试中验证,然后在生产环境中通过观察 CPU 利用率来验证。
原文作者:IT枫斗者;如有侵权,请联系管理员删除。