无限循环的线程是不是会导致 CPU 过多

Posted

技术标签:

【中文标题】无限循环的线程是不是会导致 CPU 过多【英文标题】:Do Threads with Infinite Loops cause excessive CPU无限循环的线程是否会导致 CPU 过多 【发布时间】:2020-06-17 15:03:19 【问题描述】:

所以这最终可能会成为一个令人尴尬的问题,但是对于 Java,线程中的无限循环会导致 CPU 使用率过高吗?我对 Java 中的多线程不是很了解,但我的假设是 Java 为所有线程分配了相同的时间,而不管线程是否有事情要做。因此,我隐含地假设多线程环境中的无限循环不会像在单线程环境中那样对性能造成负担。结果,我有很多看起来像下面sn-p的代码:

public Thread readerThread = new Thread() 
  @Override
  public void run() 
    while(true) 
      readNextMessage(); // Does nothing if there are no messages to read
    
  

readerThread.start();

我最近开始注意到我的应用程序存在严重的性能问题,我开始怀疑我的线程方法是否是原因。

【问题讨论】:

【参考方案1】:

不可能将时间分配给无关的线程。只有准备好运行的线程才能被调度。被阻塞等待某事发生的线程尚未准备好运行。

想象一下,如果您的假设是正确的,并且服务器有 100 个线程,每个客户端一个线程。现在,想象一下,这些客户中的大多数都是不活跃的。这意味着每个活动客户端最多可以获得 1/100 的 CPU。那会很糟糕。

在无事可做时消耗 CPU 的线程会阻止 CPU 进入睡眠状态、浪费电力并降低性能,不仅对同一进程中的其他线程而且对整个系统都是如此。

【讨论】:

【参考方案2】:

如果你可以保证系统总是有比准备运行的线程数更多的 CPU 来运行线程,那么像这样的“忙循环”是没有问题的。*但是,当其他线程必须等待他们的 CPU 时间的“公平份额”,通过不断检查是否有任何工作要做,并且不断地检查是否有任何工作要做,让一个线程浪费它自己的 CPU 时间份额是没有帮助的没有找到。

我的假设是 Java 为所有线程分配了相同的时间。

这是一个误解。系统将尝试为每个需要 CPU 时间的线程分配“公平份额” 987654321@ 调用,在Thread.sleep(...) 调用中阻塞等,然后该线程退出运行,并将其“公平份额”分配给其他线程,直到它“唤醒”并再次准备好运行。


* 如果忽略功耗。执行指令(甚至是无用的指令)的 CPU 比处于“等待中断”状态的 CPU 使用更多的电力。像这样的循环将导致系统使用更多的电力。这可能超出小型嵌入式系统的功率预算,或者可能导致个人计算机大幅减速以防止过热。 [PC(尤其是笔记本电脑和移动设备)的热管理是建立在 CPU 只会在短时间内使用的假设之上的。]

【讨论】:

100% 不同意你的第一句话。一方面,许多现代 CPU 的时钟速度受到温度的限制。如此繁忙的循环会增加温度,从而降低时钟速度,从而降低性能。它们还会显着影响功耗,这对于高端台式机来说是一个巨大的问题,空闲 CPU 消耗 12W,繁忙的 CPU 消耗 100W。

以上是关于无限循环的线程是不是会导致 CPU 过多的主要内容,如果未能解决你的问题,请参考以下文章

为啥意外的无限循环会增加 CPU 使用率?

如何将运行无限循环的线程限制为 1 个核心?

具有无限循环和 thread.sleep 高 CPU 使用率的多个线程

为啥这会导致无限循环

React 限制渲染次数以防止无限循环...重新渲染次数过多

EventQueue.isDispatchThread() 中的无限循环