18

在 Java 中创建 FixedThreadPool Executor 对象时,您需要传递一个参数来描述 Executor 可以并发执行的线程数。我正在构建一个服务类,其职责是处理大量电话号码。对于每个电话号码,我需要执行 Web 服务(这是我的瓶颈),然后将响应保存在哈希图中。

为了减少这个瓶颈对我的服务性能的危害,我决定创建 Worker 类来获取未处理的元素并处理它们。Worker 类实现了 Runnable 接口,我使用 Executor 运行 Worker。

可以同时运行的Workers数量取决于Executor FixedThreadPool的大小。ThreadPool 的安全大小是多少?当我使用一些大数字作为参数创建 FixedTheradPool 时会发生什么?

4

9 回答 9

8

可以考虑的东西正在看

Runtime.getRuntime().availableProcessors()

这为对系统有意义的线程数量提供了一些指导。

于 2010-07-12T02:27:38.593 回答
6

如果每个工作线程都需要进行 Web 服务调用,那么池中的线程数应该受到 Web 服务可以处理的同时请求数量的强烈影响。比这更多的线程只会压倒 Web 服务。

于 2009-06-22T18:30:54.017 回答
2

我在某处读到最佳线程数是内核数 * 25。似乎 .NET 将其用作 ThreadPool 的默认值。但是,如果您有大量 Web 服务调用,您最好使用单个线程并检查 Web 服务调用列表以获取响应。当响应到达时,只需处理条目并将其从列表中删除。

于 2009-06-22T18:30:19.590 回答
2

如果您拥有对 Web 服务的开发人员访问权限,请考虑创建一个批处理功能以在一次通话中检查多个电话号码。

在较新的 .NET 中,有一个 ThreadPool 可以根据自己的性能配置文件增长和缩小。不幸的是,Java 的版本要么是固定的,要么会根据传入的工作增长到一个限制。

我们曾经有过类似的担忧。我们的解决方案是让客户根据自己的喜好调整池大小并调整性能。

对于 I/O 操作池的大小调整,可以考虑一些网络和数据属性:网络带宽、消息大小、处理时间和 Web 服务的样式、本地内核的数量。

于 2009-06-22T18:35:01.327 回答
2

如果每次计算都相当于对 Web 服务的调用,那么您应该考虑对该服务施加了多少负载/该服务将容忍或允许服务所有者允许多少并发连接。大多数可公开访问的服务一次只期望来自任何单个用户的一个这样的连接。如果可能,请联系服务的所有者了解他们的使用政策。此类连接的数量将决定您可以使用的线程数。

于 2009-06-22T18:35:05.977 回答
1

让我们假设 Web 服务是无限可扩展的,并且没有人会关心您向它发送垃圾邮件请求。我们还假设 Web 服务响应在 1 秒范围内,而本地处理时间为 5 毫秒。

当您拥有与处理核心相同数量的繁忙线程时,吞吐量会最大化。

在这些假设下,对于任何合理大小的线程池,您将无法在多核处理器上最大化吞吐量。要实现每秒最大事务数,您必须打破每个连接模型的线程。寻找前面提到的非阻塞 I/O (NIO) 或异步完成令牌模式的 Java 实现(Windows 中的 IO 完成)。

请注意,为每个创建的线程保留的堆栈内存实际上只是保留的地址空间,而不是实际分配或提交的内存。当堆栈尝试增长时,会引发异常,从而导致堆栈内存按需提交。结果是它只与 32 位内存管理器真正相关。对于 64 位内存,您有一个巨大的地址空间,即使您只用物理内存支持该空间的一小部分。至少,这是我理解 Windows 工作的方式,我不确定 Unix 世界。

于 2009-06-22T20:38:46.877 回答
0

不要忘记,您创建的每个线程也会对其堆栈大小提出内存需求。因此,创建线程池将影响进程的内存占用(请注意,某些池在实际需要它们之前不会创建线程,因此在启动时您不会看到任何内存增加)。

此堆栈大小可通过-Xss(类似于-Xmxetc.)进行配置。我相信默认值是每个线程 512Kb。目前我找不到任何权威来证实这一点。

于 2009-06-22T18:40:01.273 回答
0

我想知道您是否最好使用 NIO 而不是线程,因为您的限制因素将是 Web 服务服务器 + 网络瓶颈,而不是客户端 CPU。

否则,您最多不应该超过您的 Web 服务可以支持的并发连接数。

于 2009-06-22T19:05:54.630 回答
0

如果您正在为并行数组操作进行大量计算,那么经验法则是线程数与处理器数相对应。

于 2009-06-22T19:16:21.083 回答