我正在處理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