假設我有以下的代碼,我wan't我的PC的多個CPU內核上擴展工作負載優化:多線程使用線程池一個for循環中完成的工作
double[] largeArray = getMyLargeArray();
double result = 0;
for (double d : largeArray)
result += d;
System.out.println(result);
在這個例子中,我可以將在for循環中完成的工作分配給多個線程,並在繼續打印result
之前驗證線程是否全部終止。因此,我想出了一些看起來像這樣:
final double[] largeArray = getMyLargeArray();
int nThreads = 5;
final double[] intermediateResults = new double[nThreads];
Thread[] threads = new Thread[nThreads];
final int nItemsPerThread = largeArray.length/nThreads;
for (int t = 0; t<nThreads; t++) {
final int t2 = t;
threads[t] = new Thread(){
@Override public void run() {
for (int d = t2*nItemsPerThread; d<(t2+1)*nItemsPerThread; d++)
intermediateResults[t2] += largeArray[d];
}
};
}
for (Thread t : threads)
t.start();
for (Thread t : threads)
try {
t.join();
} catch (InterruptedException e) { }
double result = 0;
for (double d : intermediateResults)
result += d;
System.out.println(result);
假設largeArray
的長度是nThreads
整除。此解決方案正常工作。
但是,我遇到了上面的for循環線程在我的程序中出現了很多問題,由於線程的創建和垃圾回收導致了很多開銷。因此,我正在通過使用ThreadPoolExecutor
來修改我的代碼。給出中間結果的線程將在下一次執行中重新使用(在本例中爲求和)。
因爲我將中間結果存儲在一個事先必須知道的大小數組中,所以我想使用一個固定大小的線程池。 但是,我有麻煩,讓一個線程知道它應該在數組的哪個地方存儲它的結果。 我應該定義我自己的ThreadFactory
嗎?
或者我更好的使用由方法Executors.newSingleThreadExecutor(ThreadFactory myNumberedThreadFactory)
創建的ExecutorService
的數組?
請注意,在我的實際程序中,很難用其他類型的東西代替double[] intermediateResults
。我更喜歡一種僅限於創建正確類型的線程池的解決方案。
如何使用ForkJoin框架?該框架允許您將大型計算工作分解爲「固定大小」片段,並將結果批量片段分配到線程池中。 Linky:http://docs.oracle.com/javase/tutorial/essential/concurrency/forkjoin.html – user268396
Java 8將於下週發佈,您的使用案例與全新'Streams' API完美搭配。 –
順便說一句,讓我向你保證,「垃圾收集的線程」不是你的問題。 –