[英]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.