java - 简单计算在多线程中比在单线程中花费更长的时间
java - Simple calculation takes longer in multi threads than in single thread
我正在尝试了解如何利用多线程。我编写了一个简单的程序,使用两种方式将 i
的值递增 400,000 次:单线程方式(0 到 400,000)和多线程方式(在我的例子中,4 次:0 到 100,000 ) 线程数等于 Runtime.getRuntime().availableProcessors()
.
我对我测量的结果感到惊讶:单线程方式明显更快,有时快 3 倍。这是我的代码:
public class Main {
public static int LOOPS = 100000;
private static ExecutorService executor=null;
public static void main(String[] args) throws InterruptedException, ExecutionException {
int procNb = Runtime.getRuntime().availableProcessors();
long startTime;
long endTime;
executor = Executors.newFixedThreadPool(procNb);
ArrayList<Calculation> c = new ArrayList<Calculation>();
for (int i=0;i<procNb;i++){
c.add(new Calculation());
}
// Make parallel computations (4 in my case)
startTime = System.currentTimeMillis();
queryAll(c);
endTime = System.currentTimeMillis();
System.out.println("Computation time using " + procNb + " threads : " + (endTime - startTime) + "ms");
startTime = System.currentTimeMillis();
for (int i =0;i<procNb*LOOPS;i++)
{
}
endTime = System.currentTimeMillis();
System.out.println("Computation time using main thread : " + (endTime - startTime) + "ms");
}
public static List<Integer> queryAll(List<Calculation> queries) throws InterruptedException, ExecutionException {
List<Future<Integer>> futures = executor.invokeAll(queries);
List<Integer> aggregatedResults = new ArrayList<Integer>();
for (Future<Integer> future : futures) {
aggregatedResults.add(future.get());
}
return aggregatedResults;
}
}
class Calculation implements Callable<Integer> {
@Override
public Integer call() {
int i;
for (i=0;i<Main.LOOPS;i++){
}
return i;
}
}
控制台:
Computation time using 4 threads : 10ms.
Computation time using main thread : 3ms.
谁能解释一下?
一个加法可能需要一个 cpu 周期,因此如果您的 cpu 运行 频率为 3GHz,则为 0.3 纳秒。执行 400k 次,就变成 120k 纳秒或 0.1 毫秒。因此,与您尝试测量的操作相比,启动线程、线程切换、JIT 编译等开销对您的测量的影响更大。
您还需要考虑编译器优化:如果您将空循环放在一个方法中并且 运行 该方法多次,您会注意到它 运行s 在 0 毫秒后时间,。因为编译器确定该循环什么都不做,并将其完全优化掉。
我建议您使用专门的库进行微基准测试,例如 jmh。
另请参阅:How do I write a correct micro-benchmark in Java?
我正在尝试了解如何利用多线程。我编写了一个简单的程序,使用两种方式将 i
的值递增 400,000 次:单线程方式(0 到 400,000)和多线程方式(在我的例子中,4 次:0 到 100,000 ) 线程数等于 Runtime.getRuntime().availableProcessors()
.
我对我测量的结果感到惊讶:单线程方式明显更快,有时快 3 倍。这是我的代码:
public class Main {
public static int LOOPS = 100000;
private static ExecutorService executor=null;
public static void main(String[] args) throws InterruptedException, ExecutionException {
int procNb = Runtime.getRuntime().availableProcessors();
long startTime;
long endTime;
executor = Executors.newFixedThreadPool(procNb);
ArrayList<Calculation> c = new ArrayList<Calculation>();
for (int i=0;i<procNb;i++){
c.add(new Calculation());
}
// Make parallel computations (4 in my case)
startTime = System.currentTimeMillis();
queryAll(c);
endTime = System.currentTimeMillis();
System.out.println("Computation time using " + procNb + " threads : " + (endTime - startTime) + "ms");
startTime = System.currentTimeMillis();
for (int i =0;i<procNb*LOOPS;i++)
{
}
endTime = System.currentTimeMillis();
System.out.println("Computation time using main thread : " + (endTime - startTime) + "ms");
}
public static List<Integer> queryAll(List<Calculation> queries) throws InterruptedException, ExecutionException {
List<Future<Integer>> futures = executor.invokeAll(queries);
List<Integer> aggregatedResults = new ArrayList<Integer>();
for (Future<Integer> future : futures) {
aggregatedResults.add(future.get());
}
return aggregatedResults;
}
}
class Calculation implements Callable<Integer> {
@Override
public Integer call() {
int i;
for (i=0;i<Main.LOOPS;i++){
}
return i;
}
}
控制台:
Computation time using 4 threads : 10ms.
Computation time using main thread : 3ms.
谁能解释一下?
一个加法可能需要一个 cpu 周期,因此如果您的 cpu 运行 频率为 3GHz,则为 0.3 纳秒。执行 400k 次,就变成 120k 纳秒或 0.1 毫秒。因此,与您尝试测量的操作相比,启动线程、线程切换、JIT 编译等开销对您的测量的影响更大。
您还需要考虑编译器优化:如果您将空循环放在一个方法中并且 运行 该方法多次,您会注意到它 运行s 在 0 毫秒后时间,。因为编译器确定该循环什么都不做,并将其完全优化掉。
我建议您使用专门的库进行微基准测试,例如 jmh。
另请参阅:How do I write a correct micro-benchmark in Java?