10

我在我的 Core i7 笔记本电脑上运行一个 Java 程序,它有 8 个内核(4 个物理,4 个 HT)。该程序使用 8 个并行线程,因此它应该耗尽所有 CPU。使用“-server”参数运行时,它始终处于 100%。没有它,它总体上大约是 50%-60%(总是随着 100% 的峰值和 30% 的下降而变化)。这就是我觉得奇怪的地方:当我在调试中运行程序并等待 CPU 使用率特别低 (30%) 的片刻,然后暂停执行以查看八个线程在做什么时,它们都没有处于阻塞状态. 此外,它们之间几乎没有同步。这就是我想知道的:

  1. 服务器和客户端虚拟机之间有什么区别会阻止客户端的 CPU 达到 100%?
  2. 在没有同步的情况下,什么可以阻止线程完全用完内核?(可能与1有关)

编辑:这是一个想法:代码分配大数组并很快将它们留给 GC。调用“new SomethingBig()”并分配该内存需要时间时,线程是否休眠?如果虚拟机中有一个进程处理一堆线程的分配,我想这可以解释为什么它们似乎在同步块之外随机暂停......

Edit2:我很确定它现在是由 GC 引起的。如果我给 VM 1500Mb 而不是默认的 500Mb,CPU 会再次达到 100%。我认为减速不会发生在服务器模式下,因为它默认使用更多内存。

4

2 回答 2

3

与Java无关,但是您拥有的线程数应该超过您必须充分利用CPU的核心数,这是因为有很多时候特定线程无法执行,以及更明显的是等待另一个线程持有的条件变量,线程也可能由于其他原因被阻塞,例如缓存未命中可能需要线程等待数据是否加载到 CPU 缓存中,它可能必须等待来自某个源的输入比cpu慢,实际上内存分页可能会导致您的线程等待。通过拥有比核心更多的线程,当一个线程由于某种原因被阻塞时,另一个线程可以使用被释放的那个核心。一个好的初始值大约是您拥有的内核数的 1.5 倍。

于 2013-02-15T13:20:22.140 回答
2

如果你想监控 Java 线程在做什么,你不应该在调试模式下运行应用程序并暂停它。

相反,您应该在 CPU 使用率下降的特定时间间隔内收集线程转储。kill -3 <pid>

与您的第二次更新相关,您应该启用带有时间戳的 GC 日志记录,并将减速/CPU 使用率下降与 Young/Full GC 收集的时间相关联。

于 2013-02-16T05:35:12.573 回答