关于多线程:从Java内部限制CPU

Throttling CPU from within Java

在这个(和其他)论坛中,我看到了很多标题相同的问题,但是似乎都没有一个问题能解决我的问题。就是这个:
我有一个JVM,它吞噬了托管它的机器上的所有CPU。我想限制它,但是我不能依赖Java外部的任何限制工具/技术,因为我无法假设该Vm将在哪里运行。因此,例如,我无法使用处理器关联性,因为如果VM在Mac上运行,则操作系统将不会提供进程关联性。

我需要指示一下Java中是否存在确保线程不占用全部CPU的方法。

我想直截了当地指出,我不能像某些论坛中所建议的那样使用基于交替执行过程和暂停的技术,因为线程需要连续生成值。

理想情况下,我想要一些平均值,例如,设置一些VM或线程优先级,或以某种方式限制CPU消耗的百分比。

任何帮助将不胜感激。


What I would need is an indication as to whether means exist within Java to ensure the thread does not take the full CPU.

除了调整应用程序以使用更少的CPU之外,我在Java中没有其他方法可以做到。

  • 您可以在计算方法中添加一些Thread.sleep(...);调用。探查器将帮助您显示热循环/方法/等。
  • 分叉更少的线程也会影响所使用的CPU。移至固定大小的线程池或减少池中的线程数。
  • 问题可能不是CPU,而是其他资源。例如,注意您的IO带宽。降低网络或磁盘读/写速度可能会使服务器恢复正常运行。

在JVM外部,您可以使用?unix nice命令来影响正在运行的JVM的优先级,以使其不支配系统。这将为它提供CPU(如果有),但将使其他应用程序获得更多的CPU。


我认为您需要比设置线程优先级更可靠的东西吗?

如果您希望节制地执行一些不断生成值的代码,则需要研究对线程所做的工作进行分块,并在自己的计时器中进行编码。例如,java.util.Timer允许以固定的速率安排执行。

当调度程序没有其他要优先执行的任务时,任何其他技术仍然会消耗尽可能多的可用CPU(每个线程1个内核,假设没有锁阻止并发执行)。


细节仅仅是您说的"必须连续生成值",如果这是极端的话,那么CPU饱和实际上就是目标。

但是,如果将"连续"定义为每秒X个值,那么仍有工作空间。

因为您可以在100%CPU上运行进程,测量一段时间内的值数量,并且如果发现它生成的值超出了必要(超过X / sec),那么现在可以在其中插入暂停直到价值率达到您期望的目标为止的过程。

该计划将持续监控和调整暂停时间,以保持您的价值率随着时间的推移。这样,您的进程将需要尽可能多的CPU以达到您的值/秒目标。

附录:

如果您有一个满意的基准值/秒,那么插入睡眠将为其他应用程序提供"所有必要的优先级",但仍可保持吞吐量。另一方面,如果您没有任何固定要求,即"在没有其他任何东西运行时,则以尽可能快的速度运行,如果其他进程主导了CPU,则对任何结果均没有实际要求",那么这确实是主机操作系统的内核问题,而不是JVM具有任何直接,可移植的机制来解决的问题。

在Unix系统上,您具有nice(1)命令来调整进程(而非线程)优先级,Windows具有其自己的机制。使用这些命令,您可以将Java进程的优先级降低到" idle"(空闲时总是运行的默认" process")的上方。但这是平台特定的,因为这是平台固有的问题。可以通过启动Java程序的特定于平台的启动脚本(甚至是在执行实际代码之前检测到平台并"执行正确的操作"的Java启动器)来管理此问题。

大多数系统将允许您降低自己的流程优先级,但是除非您是管理员/超级用户或对您的主机操作系统具有适当角色,否则很少有系统会让您提高。


检查代码中是否有"紧密循环"。

1
2
3
4
5
while (true) {
  if (object.checkSomething()) {
    ...
  }
}

如果您这样做,那么您将在数以百万计的检查中消耗CPU周期,而这些检查可能不是那么关键。 JVM将强制执行(因为它不知道检查是否"重要"),并且您将获得100%的CPU。

如果找到这样的循环,请像这样重写它们

1
2
3
4
5
6
7
8
9
10
while (true) {
  if (object.checkSomething()) {
    ...
  }
  try {
    Thread.sleep(100);
  } catch (InterruptedException e) {
    // purposefully do nothing
  }
}

并且睡眠将自动在循环内释放CPU,从而防止其运行太快(并检查状态太多次)。


非常有趣的线程。我发现Java不提供执行我想做的事情的方法,而唯一的方法是从JVM外部执行。
我最终使用nice来更改测试(Linux)环境中的调度优先级,仍然需要为基于WIn的OS找到类似的东西。

每个人的干预都倍受赞赏。