为什么Java不能有效地利用我所有的CPU内核
我在一台具有四核CPU的机器上运行Ubuntu。我已经编写了一些测试Java代码,这些代码生成了给定数量的进程,这些进程只是在运行时为给定次数的迭代递增易失性变量。
我希望运行时间不会显着增加,而线程数小于或等于内核数,即4。实际上,这些是我从UNIX命令使用“实时”的时间:time
1 条线程:1.005 秒
2 条线程:1.018 秒
3 条线程:1.528 秒
4 条线程:1.982 秒
5 条线程:2.479 秒
6 条线程:2.934 秒
7 条针:3.356 秒
8 条主题:3.793 秒
这表明添加一个额外的线程不会像预期的那样增加时间,但随着 3 个线程和 4 个线程的增加,时间确实会增加。
起初,我认为这可能是因为操作系统阻止了JVM使用所有内核,但是我运行了,它清楚地表明,使用3个线程,3个内核以〜100%的速度运行,并且使用4个线程,4个内核被最大化。top
我的问题是:为什么在3/4 CPU上运行的代码与在1/2上运行时的速度大致相同?因为它在所有内核上并行运行。
以下是我的主要参考方法:
class Example implements Runnable {
// using this so the compiler does not optimise the computation away
volatile int temp;
void delay(int arg) {
for (int i = 0; i < arg; i++) {
for (int j = 0; j < 1000000; j++) {
this.temp += i + j;
}
}
}
int arg;
int result;
Example(int arg) {
this.arg = arg;
}
public void run() {
delay(arg);
result = 42;
}
public static void main(String args[]) {
// Get the number of threads (the command line arg)
int numThreads = 1;
if (args.length > 0) {
try {
numThreads = Integer.parseInt(args[0]);
} catch (NumberFormatException nfe) {
System.out.println("First arg must be the number of threads!");
}
}
// Start up the threads
Thread[] threadList = new Thread[numThreads];
Example[] exampleList = new Example[numThreads];
for (int i = 0; i < numThreads; i++) {
exampleList[i] = new Example(1000);
threadList[i] = new Thread(exampleList[i]);
threadList[i].start();
}
// wait for the threads to finish
for (int i = 0; i < numThreads; i++) {
try {
threadList[i].join();
System.out.println("Joined with thread, ret=" + exampleList[i].result);
} catch (InterruptedException ie) {
System.out.println("Caught " + ie);
}
}
}
}