在这个(和其他)论坛中,我看到了很多标题相同的问题,但是似乎都没有一个问题能解决我的问题。就是这个:
我有一个JVM,它吞噬了托管它的机器上的所有CPU。我想限制它,但是我不能依赖Java外部的任何限制工具/技术,因为我无法假设该Vm将在哪里运行。因此,例如,我无法使用处理器关联性,因为如果VM在Mac上运行,则操作系统将不会提供进程关联性。
我需要指示一下Java中是否存在确保线程不占用全部CPU的方法。
我想直截了当地指出,我不能像某些论坛中所建议的那样使用基于交替执行过程和暂停的技术,因为线程需要连续生成值。
理想情况下,我想要一些平均值,例如,设置一些VM或线程优先级,或以某种方式限制CPU消耗的百分比。
任何帮助将不胜感激。
- 您想知道Java中是否有一些API指示JVM允许其他线程/应用程序运行?最接近的是Thread.yield()或setPriority()-但是这些API没有任何保证。
-
Thread.yield()无法解决他的问题。完全不会减慢JVM @noahz的速度。
-
您对"减慢JVM速度"的定义是什么?您意识到JVM最终会将您的字节码编译为机器指令,对吗?除非您的代码中有说明使其缓慢运行(即Thread.sleep()),否则您无法通过JVM设置使其"缓慢运行"。
-
谢谢大家这并没有降低JVM的速度,而是希望有一种方法来设置在JVM之外可以识别的优先级。设置线程的优先级时,该优先级仅在JVM内部有效,而在JVM外部无效。理想情况下,我需要类似但在系统过程级别认可的东西。希望我设法正确地解释自己:-)
-
相关:stackoverflow.com/questions/1202184/…
-
我本以为必须进行某种间歇性的暂停,除非您想具体限制允许运行程序的CPU内核数。您为什么要限制程序-以节省功率或释放CPU功率供其他应用程序使用?
-
您可以查看可用处理器的数量,并根据该数量限制线程池的大小。
-
@assylias:我已经看过这个问题,但是对此问题的答复通常倾向于解决与内存有关的问题,而不是CPU。此外,建议的方法基于暂停应用程序,这不是我想要的。实际上,在我的问题中,我放置了一个免责声明,说我对基于执行和暂停的技术并不感兴趣:-)
-
@Jimpanzee:我想找到一种方法来确保JVM仅在CPU实际可用时才占用所需的CPU,而在需要回收时将其留给更重要的系统进程。
-
我唯一能想到的就是尝试从程序内部监视系统CPU使用率,然后使用它确定循环中Thread.sleep()的毫秒数(如果有的话)。
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。
- 谢谢格雷。我知道我的问题出在CPU上,而没有其他资源。另外,我的应用程序是单线程的,它是一个生成和发送消息的简单线程。一切都在主线程中完成,没有线程池或任何形式的派生。
-
@Diferdin那么您的应用程序在单核计算机上运行吗?
-
正如我的帖子中提到的@Diferdin一样,我会考虑使用nice降低进程的OS优先级。如果有的话,这将为其他系统应用程序提供更多资源。因此,它将消耗CPU但不会占据主导地位。
-
仅供参考-即使您的应用程序是单线程的,除非您使用cpuset之类的工具,否则操作系统都可以将其移至不同的内核。
-
@灰色:谢谢!您是否有一个指针,可以在其中找到一些关于什么是不错的信息? (我实际上在您的原始答复中认为这是错字!:-))
-
@noahz:我相信您提到的名称称为"处理器相似性",并且在我的电子邮件中提到了它。这正是为什么我不能/不希望使用Java外部的方法,为什么不能在此类的运行位置以及某些操作系统(例如MacOS)不允许您调整亲和力的原因
-
@Diferdin在这种情况下,您可能无法对使用哪种JVM作任何假设,因为它们各自具有不同的功能。获得的唯一保证是Java SDK(如果使用的是Java Standard Edition),Java语言规范和Java虚拟机规范(描述字节码等,不是JVM专有供应商功能)中的功能。因此,正如其他人指出的那样,您将必须对代码承担一些责任,并自己"限制"代码。
-
@noahz:并非完全正确:-)我们可以推荐虚拟机类型和/或版本,但是我们需要保证我们推荐的一切都可以在所有操作系统上使用...
-
嗨,我在本主题的底部接受了我自己的答案,因为其他所有人都没有完全解决我的问题。
-
哦,抱歉@Diferdin。没看到。接受您自己的信息是可以的,尽管我看不到您答案中没有的任何信息。我推荐了很好的例子。但是无所谓。
-
@灰色让我改一下。我最终使用了nice,因为没有什么真的是我想要的。是的,我对您的回答表示满意,但我想表明这不是我的第一选择。谢谢你! :-)
我认为您需要比设置线程优先级更可靠的东西吗?
如果您希望节制地执行一些不断生成值的代码,则需要研究对线程所做的工作进行分块,并在自己的计时器中进行编码。例如,java.util.Timer允许以固定的速率安排执行。
当调度程序没有其他要优先执行的任务时,任何其他技术仍然会消耗尽可能多的可用CPU(每个线程1个内核,假设没有锁阻止并发执行)。
-
1我完全同意这种方法。当然,OP需要弄清楚代码的哪一部分消耗了如此多的CPU,因此我还建议使用某种类型的探查器。另外,由于可能无法获得CPU负载,因此该方法需要可调优,以便可以在不同的系统上进行调整。
-
通过OP的后续评论,我认为他的问题的核心是:"可以将JVM设置为包括文件系统,网络等在内的各种内容的沙箱。JVM是否还可以提供一个沙箱,从而甚至限制了较差的性能。编写的程序对主机系统处理器的影响。理想情况下,这需要以非JVM实现特定的方式(例如JMX)来控制。"
-
我在某种程度上同意;我希望有一个基于优先级的机制,但是标准的Java线程优先级机制仅在JVM内具有有效性,而我需要类似的东西但在OS /内核级别具有有效性。我理想上希望的是一种告诉JVM在可用时使用完整CPU的方法,并在其他可能更重要的系统进程需要它时减轻某些负担。
-
@Diferdin,应该是在JVM上运行的常规程序(没有用于管理优先级等的特殊代码)的行为。如果JVM没有表现出这种行为,我认为您的OS不能完成其工作。
细节仅仅是您说的"必须连续生成值",如果这是极端的话,那么CPU饱和实际上就是目标。
但是,如果将"连续"定义为每秒X个值,那么仍有工作空间。
因为您可以在100%CPU上运行进程,测量一段时间内的值数量,并且如果发现它生成的值超出了必要(超过X / sec),那么现在可以在其中插入暂停直到价值率达到您期望的目标为止的过程。
该计划将持续监控和调整暂停时间,以保持您的价值率随着时间的推移。这样,您的进程将需要尽可能多的CPU以达到您的值/秒目标。
附录:
如果您有一个满意的基准值/秒,那么插入睡眠将为其他应用程序提供"所有必要的优先级",但仍可保持吞吐量。另一方面,如果您没有任何固定要求,即"在没有其他任何东西运行时,则以尽可能快的速度运行,如果其他进程主导了CPU,则对任何结果均没有实际要求",那么这确实是主机操作系统的内核问题,而不是JVM具有任何直接,可移植的机制来解决的问题。
在Unix系统上,您具有nice(1)命令来调整进程(而非线程)优先级,Windows具有其自己的机制。使用这些命令,您可以将Java进程的优先级降低到" idle"(空闲时总是运行的默认" process")的上方。但这是平台特定的,因为这是平台固有的问题。可以通过启动Java程序的特定于平台的启动脚本(甚至是在执行实际代码之前检测到平台并"执行正确的操作"的Java启动器)来管理此问题。
大多数系统将允许您降低自己的流程优先级,但是除非您是管理员/超级用户或对您的主机操作系统具有适当角色,否则很少有系统会让您提高。
-
谢谢,如果是这种情况,那么让我改写一下:我想让JVM使用尽可能多的CPU,但是要在其他更重要的系统进程确实需要它的时候释放一些CPU
检查代码中是否有"紧密循环"。
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,从而防止其运行太快(并检查状态太多次)。
-
很好,但是使用某种类型的探查器可能会更容易,更安全。您不希望最终"优化"一些不需要优化的东西,这可能会使情况变得更糟。尽管答案是针对不同的语言和技术,但我认为概念是相同的:stackoverflow.com/questions/10800372/…
-
消除紧密循环并不是一种优化。消除紧密的循环可以纠正不良的设计。将其视为性能错误,由仅将错误视为影响代码完成的人员造成。
-
对于错误的定义和错误的设计,我同意您的看法,但是始终最好使用良好的探查器。
非常有趣的线程。我发现Java不提供执行我想做的事情的方法,而唯一的方法是从JVM外部执行。
我最终使用nice来更改测试(Linux)环境中的调度优先级,仍然需要为基于WIn的OS找到类似的东西。
每个人的干预都倍受赞赏。