我正在处理Java中的多线程问题,正如有人向我指出的那样,我注意到线程正在热身,就是说,它们在重复执行时变得更快。我想了解为什么会发生这种情况,以及它是否与Java本身有关,或者它是否是每个多线程程序的常见行为。在多线程处理中,“预热”线程究竟是什么?
在于举例说明它是下面的代码(由Peter Lawrey):
for (int i = 0; i < 20; i++) {
ExecutorService es = Executors.newFixedThreadPool(1);
final double[] d = new double[4 * 1024];
Arrays.fill(d, 1);
final double[] d2 = new double[4 * 1024];
es.submit(new Runnable() {
@Override
public void run() {
// nothing.
}
}).get();
long start = System.nanoTime();
es.submit(new Runnable() {
@Override
public void run() {
synchronized (d) {
System.arraycopy(d, 0, d2, 0, d.length);
}
}
});
es.shutdown();
es.awaitTermination(10, TimeUnit.SECONDS);
// get a the values in d2.
for (double x : d2) ;
long time = System.nanoTime() - start;
System.out.printf("Time to pass %,d doubles to another thread and back was %,d ns.%n", d.length, time);
}
结果:
Time to pass 4,096 doubles to another thread and back was 1,098,045 ns.
Time to pass 4,096 doubles to another thread and back was 171,949 ns.
... deleted ...
Time to pass 4,096 doubles to another thread and back was 50,566 ns.
Time to pass 4,096 doubles to another thread and back was 49,937 ns.
即它变得更快,稳定在50纳秒左右。这是为什么?如果我运行这个代码(20次重复),然后执行其他的事情(让我们说对前面的结果进行后处理,并准备进行另一次多线程操作),然后在同一个ThreadPool
上执行同样的Runnable
再进行20次重复,它会无论如何,已经被预热了?在我的程序中,我只在一个线程中执行Runnable
(实际上每个处理核心有一个,它是一个CPU密集型程序),然后是其他一些串行处理交替进行多次。随着程序的执行,它似乎并没有变得更快。也许我可以找到一种方法来预热它...
感谢您的解释,@ rfeak。但是你认为编译器能够优化我的程序吗? (请阅读我在问题中添加的最后一段) – ursoouindio 2011-03-04 20:17:15
JIT编译器只能做这么多,只影响CPU时间。如果串行进程涉及任何类型的IO,编译器几乎无法完成。我会建议分析你的程序,看看时间花在哪里,然后攻击那里最大的瓶颈,如果你需要更多的性能。 – rfeak 2011-03-04 20:47:46
实际上,它没有任何IO。我给出了初始条件,程序是由它自己运行的。我解决了一些特殊的微分方程。 – ursoouindio 2011-03-04 23:12:11