Java CPU使用率应该是100%......但事实并非如此

时间:2013-02-15 11:27:53

标签: java multithreading jvm

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

  1. 服务器和客户端虚拟机之间有什么区别会阻止CPU在客户端达到100%?
  2. 在没有同步的情况下,什么可能让线程完全耗尽核心? (可能与1相关)
  3. 编辑:这是一个想法:代码分配大数组并很快将它们留给GC。调用'new SomethingBig()'并分配该内存需要时间时线程是否会休眠?如果VM处理一组线程的分配中有一个进程,我想这可以解释为什么它们似乎在同步块之外随机暂停......

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

2 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:2)

如果要监视Java线程正在执行的操作,则不应在调试模式下运行App并暂停它。

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

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