[英]Why is my ExecutorService implementation performing worse than single threaded implementation?
我一直在嘗試多線程康威的生命游戲程序。 我天真的解決方案的一部分是大致做我在下面所做的事情。 然而,即使這個基本實現的性能也比單線程解決方案差得多,這突出了我不理解某些東西的事實。
我還應該說,如果不清楚,我需要在 while 循環的每次迭代結束時“加入”線程,這就是我使用 Callable 的原因 - 這樣我就可以獲得並迭代 Futures .
任何反饋,意見建議將非常受歡迎。
package lewi0231.testOne;
import java.util.ArrayList;
import java.util.concurrent.*;
public class LongRunningTask {
int count;
boolean[][] board = new boolean[200][200];
ExecutorService threadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
public LongRunningTask(int count) {
this.count = count;
}
public void processTask() {
int i = 0;
ArrayList<Future<Integer>> futures = new ArrayList<>();
while(i < count){
for (int k = 1; k < board.length; k++){
futures.add(threadPool.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
for (int l = 1; l < board[0].length; l++){
//Do Something Here
}
return 1;
}
}));
}
for (Future<Integer> f : futures){
try {
f.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
i++;
}
}
}
class HypotheticalGUI{
public static void main(String[] args) {
LongRunningTask task = new LongRunningTask(100);
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
task.processTask();
}
});
thread.start();
}
}
當線程(運行)的數量明顯超過可用處理器的數量時,可能會發生過多的上下文切換。 這意味着創建線程的開銷加上在線程之間切換的開銷會影響性能。
上下文切換尤其具有破壞性,因為每當處理器從一個線程切換到另一個線程時,它必須刷新其緩存並重新加載新線程的上下文。 這種意義上的上下文是指線程的堆棧、寄存器和程序計數器的內容。
更好的方法是嘗試將可用處理器的數量與創建的線程數量相匹配。 見下文:
import java.util.ArrayList;
import java.util.concurrent.*;
public class LongRunningTask {
int count;
boolean[][] board = new boolean[200][200];
int numProcessors = Runtime.getRuntime().availableProcessors() - 1;
ExecutorService threadPool = Executors.newFixedThreadPool(numProcessors);
public LongRunningTask(int count) {
this.count = count;
}
public void processTask() {
int i = 0;
ArrayList<Future<Integer>> futures = new ArrayList<>();
int startIndex = 1;
int partitionSize = board.length / numProcessors;
while(i < count){
while (startIndex < board.length) {
futures.add(threadPool.submit(new MyCallable(startIndex, partitionSize, board)));
startIndex += partitionSize;
}
for (Future<Integer> f : futures){
try {
f.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
i++;
}
}
}
class MyCallable implements Callable<Integer> {
private final int startIndex;
private final int partitionSize;
private final boolean[][] board;
public MyCallable(int startIndex, int partitionSize, boolean[][] board){
this.startIndex = startIndex;
this.partitionSize = partitionSize;
this.board = board;
}
@Override
public Integer call() throws Exception {
int endIndex = Math.min(startIndex + partitionSize, board.length - 1);
for (int k = startIndex; k < endIndex; k++){
for (int l = 1; l < board[0].length; l++){
//Do Something Here
}
}
return 1;
}
}
class HypotheticalGUI{
public static void main(String[] args) {
LongRunningTask task = new LongRunningTask(100);
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
task.processTask();
}
});
thread.start();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.