Java多线程会在较长的过程中减慢速度,最大程度地提高CPU使用率

时间:2018-11-14 23:05:27

标签: java multithreading

我正在用Eclipse开发Java程序,该程序可以分析大型物理数据集并运行迭代优化过程。在对具有大量迭代的特别大的数据集进行测试时,我看到了我无法解释的现象。

以下是设置线程的方式:

List<String> scenarios;    
List<Thread> threads = new ArrayList<Thread>();
final int cores = Runtime.getRuntime().availableProcessors() - 1;

for(final String scenario: scenarios) {
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                innerLoopParallel(); //each optimization iteration
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        if(threads.size() < cores) {
            thread.start();
            threads.add(thread);
        }
    }
    for (Thread thread: threads) {
        try {
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

我的机器有8个核心,我正在多线程化到7个核心上。迭代过程最初运行时确实非常快,但是运行约20分钟后,其运行速度却相当慢。我最初的想法是内存限制,但是我一直在关注堆状态(在Eclipse中,Window->首选项->常规->“显示堆状态”),而且似乎并没有达到极限。但是,我的CPU已经用光了(见图),风扇猛烈吹动。在每次迭代时,都应该在控制台上打印一行,但是随着程序速度的降低,它开始成块写入,每次打印20条。

Max CPU Usage

我知道这个问题有些含糊,但我的想法已经用完了。您有什么建议可以指示我正确的方向吗?多线程会引起问题吗? for循环是否有可能通过不关闭某些进程而以某种方式建立CPU?如果您需要任何澄清,请随时提出问题。

1 个答案:

答案 0 :(得分:1)

  

您有什么建议可以指示我正确的方向吗?

使用探查器来找出应用程序在所有时间上所花费的时间。

  

多线程是否会引起问题?

可能。尤其是如果您创建了太多线程和/或在线程之间进行了太多上下文切换。

  

for循环是否有可能通过不关闭某些进程而以某种方式建立CPU?

这个问题(对我而言)真的没有意义。

但是,由于循环要在越来越大的数据结构上运行,因此循环花费的时间越来越长是合理的。还有很多其他可能的原因导致算法会随着时间的推移变得非常缓慢/非常占用CPU。

建议:

  • 分析您的代码/算法以及使用线程的方式。
  • 考虑进行Big O复杂性分析。
  • 请考虑您的应用程序是否由于非本地化的内存访问模式而导致过多的内存争用和高速缓存崩溃。

更新

我可以看到您的线程代码有问题。例如,看起来某些线程永远不会启动。但是 1 也有明显迹象表明这不是真实代码,因此对其进行分析很有用。

但是,我不应该那样做,而应该使用ExecutorService和叉连接池中有界的线程池。 (不确定哪个是最好的...。因为您的示例代码太抽象了。)进行自己的线程池管理不是一个好主意,而且已经20多年了!

另一方面,没有一种或多种方式的真实证据表明线程是问题所在。请参阅我的早期建议!


1-例如,监视显示有超过2500个本机线程。但是,您显示给我们的代码不应该发生这种情况。