代码之家  ›  专栏  ›  技术社区  ›  Pavel Feldman

休眠和等待线程消耗了多少资源

  •  19
  • Pavel Feldman  · 技术社区  · 18 年前

    我想知道,在java 1.6 x64中让许多线程处于等待状态有多昂贵。

    更具体地说,我正在编写一个跨多台计算机运行并从一台计算机向另一台计算机发送/接收数据的应用程序。我觉得为每台连接的机器和任务设置单独的线程更舒服,比如1)发送数据,2)接收数据,3)在连接断开时重新建立连接。因此,假设集群中有N个节点,每台机器将为N-1个邻居中的每一个拥有3个线程。通常会有12台机器,总共33个通信线程。

    这些线程中的大多数将在大部分时间处于休眠状态,因此出于优化目的,我可以减少线程数量,并为每个线程分配更多任务。例如。重新建立连接是接收线程的责任。或者发送到所有连接的机器是通过单线程完成的。

    那么,拥有多条睡眠线对性能有任何重大影响吗?

    5 回复  |  直到 13 年前
        1
  •  15
  •   Liedman    18 年前

    在大多数情况下,睡眠线程消耗的资源将是它的堆栈空间。使用每个连接2个线程的模型(我认为这与您所描述的类似),众所周知,当连接数量增长时,会导致很大的可扩展性问题。

    我自己也遇到过这种情况,当连接数量超过500个连接(大约1000个线程)时,你往往会遇到很多情况,你会得到OutOfMemoryError,因为线程堆栈空间的使用超过了单个进程的最大内存量。至少在我们的例子中,这是在32位Windows上的Java世界中。我想,你可以调整一些东西,走得更远,但最终它不是很可扩展,因为你浪费了大量的内存。

    如果你需要大量的连接,Java NIO(新IO或其他)是你的选择,它可以在同一个线程中处理大量的连接。

    话虽如此,在一个相当现代的服务器上,线程数不到100个也不会遇到太大问题,即使这可能仍然是浪费资源。

        2
  •  2
  •   knatten Ciro Santilli OurBigBook.com    18 年前

    在切换到NIO之前,我们遇到了非常相似的问题,所以我会推荐Liedmans使用该框架。你应该可以找到一个教程,但如果你想了解细节,我可以推荐 Java NIO 罗恩·希钦斯。

    转向NIO增加了我们可以处理的连接数量,这对我们来说非常重要。

        3
  •  1
  •   Matt Howells    18 年前

    这不会很好地扩展。拥有大量线程意味着VM必须花费更多的时间进行上下文切换,并且由于每个线程都需要自己的堆栈空间,因此内存使用率会更高。您最好以流水线方式处理较少的线程,或者使用具有异步技术的线程池。

        4
  •  1
  •   Bill Michell    18 年前

    很多线程等于很多堆栈空间,这会占用你的内存——看看你的-Xss设置到底有多少,然后计算一下。

    如果你因为某种原因必须执行notifyAll(),那么你当然会唤醒大量额外的线程——尽管在你提出的架构中可能不需要这样做。

    我不确定在这个模型中,你能很容易地避免每个监听套接字有一个线程(尽管我对NIO知之甚少,它甚至可能解决这个问题),但看看 java.util.concurrent.Executor 接口及其实现类,以一种体面的方式避免有太多额外的线程。事实上 ThreadPoolExecutor 这可能也是管理你的监听线程的好方法,这样你就不会花太多时间不必要地创建和销毁线程。

        5
  •  0
  •   Mossarelli    9 年前

    根据我在C、Lua和Python中做的测试,你可以用很少的代码行来创建自己的sleep或wait函数,从而创建一个简单的轻量级循环。 使用一个包含您希望到达的未来时间的局部变量,然后在while循环中测试当前时间戳。如果您在使用fps的范围内,请使wait函数每帧运行一次以节省资源。 您需要的精度越高,请考虑使用时钟而不是时间戳,因为时间戳仅限于秒。 你添加到等待函数中的代码行越多,它就越不精确,消耗的资源就越多,尽管任何少于10行的代码都应该足够快。