【问题标题】:Reasonable number of threads for thread pool running web service requests线程池运行Web服务请求的合理线程数
【发布时间】:2010-11-04 22:46:54
【问题描述】:

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

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

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

【问题讨论】:

  • 你好迈克尔,几点:你认为“大量电话号码”是什么?您的应用程序将运行的系统规格是什么?当使用批处理特定线程时,可用的内存量。计算还考虑了堆和处理器速度。最好的问候,Kam。
  • 除此之外,请阅读此处的类比:java.sun.com/docs/books/tutorial/essential/concurrency/… 看看您的应用程序是否适合 FixedThread Pools 的漏洞。

标签: java web-services concurrency threadpool


【解决方案1】:

可以考虑的东西在看

Runtime.getRuntime().availableProcessors()

它给出了多少线程对系统有意义的方向。

【讨论】:

  • 网络服务调用可能主要是 IO 等待,因此与 CPU 数量没有直接关系
【解决方案2】:

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

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

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

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

      • 是的 - 这是一个很好的方向,但是你能推荐一个像样的 NIO Web 服务客户端实现吗?
      【解决方案5】:

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

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

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

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

      【讨论】:

        【解决方案6】:

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

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

        【讨论】:

        • 是的,在 Linux 上,每个线程都有自己的堆栈,默认大小为 512kB。
        • 我找不到详细说明多个平台的最新参考。如果你能找到一个,我会适当地改变答案。
        【解决方案7】:

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

        【讨论】:

          【解决方案8】:

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

          【讨论】:

          • http行为就像他的FixedThreadPool,不用担心调用和得到响应。主要问题是处理的质量大小,内存利用率。堆和机器的速度。
          【解决方案9】:

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

          【讨论】:

          猜你喜欢
          • 2013-11-15
          • 1970-01-01
          • 2018-07-19
          • 2015-11-15
          • 2015-03-27
          • 2013-06-01
          • 2010-12-15
          • 2014-11-16
          • 2021-01-12
          相关资源
          最近更新 更多