[英]threading work results are unexpected - java
我是多線程新手。 我正在開發一個程序,將一個包含許多記錄(300 萬個整數)的文件讀入某個鏈接列表,然后一些線程處理每個列表並計算列表的總和,找到最大值和最小值。 然后主線程比較子線程結果並顯示最終結果。
程序使用此命令:
計算 -f 文件路徑 -t 線程數
現在的問題是,當我用一個線程運行程序時,它比某些線程花費的時間少。
我的CPU是酷睿i7。
這是一段時間的結果:
(線程:持續時間)--> (1 : 16) , (2,3 : 32) , (4,5,6,7 : 47) , (8,9 : 31) ... (17,18,19 ,20 : 16)
該項目有2個項目:
工人階級:
public class Worker implements Runnable {
private List<Integer> records;
private long[] res;
private String name;
Worker(String name, LinkedList<Integer> list, long[] res) {
this.records = list;
this.res = res;
this.name = name;
}
@Override
public void run() {
long startTime = System.currentTimeMillis();
long sum = 0;
int max, min;
if (records != null && records.size() > 0) {
max = min = records.get(0);
for (Integer num : records) {
sum += num;
if (num > max)
max = num;
if (num < min)
min = num;
}
long endTime = System.currentTimeMillis();
long duration = endTime - startTime;
res[0] = sum;
res[1] = max;
res[2] = min;
res[3] = duration;
System.out.println(name + "\t->\ttime:\t" + duration + "\t, Records:\t" + records.size());
}
}
}
主要類:
public class Main {
public static void main(String[] args) {
//read command and get inputs:
System.out.println("Welcome to my app : ");
while (true) {
Scanner scanner = new Scanner(System.in);
String command = scanner.nextLine().trim();
if (command.startsWith("compute")) {
command = command.substring("compute".length() + 1);
args = command.split(" ");
} else {
System.out.println("wrong command.. this app only support 'compute'");
exit(1);
}
Map<String, String> map = new HashMap<>(); //-p processes , -f filepath
for (int i = 0; i < args.length - 1; i += 2)
map.put(args[i], args[i + 1]);
File txtFile = new File(map.get("-f").trim());
final int threadCount = Integer.parseInt(map.get("-t").trim());
ArrayList<LinkedList<Integer>> lists = readFile(txtFile, threadCount);
if (lists == null) {
System.out.println("Error: can not found txt file..");
exit(2);
}
long[][] results = new long[threadCount][4];
Thread[] thread = new Thread[threadCount];
for (int i = 0; i < threadCount; i++) {
thread[i] = new Thread(new Worker("thread " + (i + 1) ,lists.get(i), results[i]));
thread[i].start();
}
boolean isAlive = true;
while (isAlive) {
isAlive = false;
for (int i = 0; i < threadCount; i++)
isAlive |= thread[i].isAlive();
}
long[] res = null;
for (long[] result : results) {
if (res != null) {
res[0] += result[0];
if (res[1] < result[1])
res[1] = result[1];
if (res[2] > result[2])
res[2] = result[2];
if (res[3] < result[3])
res[3] = result[3];
} else {
res = result;
}
}
if (res != null) {
System.out.println("sum : " + res[0]);
System.out.println("max : " + res[1]);
System.out.println("min : " + res[2]);
System.out.println("duration : " + res[3]);
}
}
}
private static ArrayList<LinkedList<Integer>> readFile(File txtFile, int procCount) {
if(!txtFile.exists() || txtFile.isDirectory())
return null;
ArrayList<LinkedList<Integer>> arrayList = new ArrayList<>();
for(int i = 0; i < procCount; i++)
arrayList.add(new LinkedList<>());
try {
int index = 0;
BufferedReader bufferedReader = new BufferedReader(new FileReader(txtFile));
String line;
while ((line = bufferedReader.readLine()) != null) {
arrayList.get(index).add(Integer.parseInt(line));
index++;
if(index == procCount)
index = 0;
}
return arrayList;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
我認為,為了學習多線程,了解阿姆達爾定律很重要。 阿姆達爾定律可用於計算通過並行運行一部分計算可加速的計算量。 我不想過多地討論技術細節,因此您可以在Wikipedia上閱讀: https : //en.wikipedia.org/wiki/Amdahl%27s_law
阿姆達爾定律從根本上說,並發計算的速度與線程數不是線性關系,線程數取決於處理器中的內核數(除非您的代碼進行網絡,IO等)。 因此,當您將線程數量加倍時,就不能指望程序將其速度提高一倍。
而且,Thread類與Java中的其他任何類一樣,將花費大量創建開銷,並且會占用大量資源。 因此,創建更多線程而沒有有效地僅對算術運算(JVM已經對其進行了非常優化)的輸入進行有效平衡時,將使程序的速度無法預測甚至變慢。
還有更多的問題需要考慮。 一個小建議是使用Java的ExecutorService
類來管理您的線程。 快樂的編碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.