我是多线程的新手,今天我试着在相同的条件下对多线程和单线程程序进行了一些性能测试。令我惊讶的是,我发现单线程选项的运行速度比多线程选项略快一些。那么可能的原因是什么呢?
我用一个字符串连接类编写了一个简单的程序,将结果写到一个文件中。我创建了5个包含50000个零的数组和5个输出文件,它们在for循环中被传递给附加器类的构造函数。在多线程选项中,我调用appender.run(),在单线程选项中,我注释掉所有与线程相关的行,并改为调用appender.appendString();
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws InterruptedException {
int[][] input = {new int[50000], new int[50000], new int[50000], new int[50000], new int[50000]};
File[] outputFiles = {new File("src\\text6.txt"), new File("src\\text7.txt"), new File("src\\text8.txt"),
new File("src\\text9.txt"), new File("src\\text10.txt")};
long startTime = System.currentTimeMillis();
Thread[] threads = new Thread[5];
for (int i = 0; i < 5; i++) {
Appender appender = new Appender(input[i], outputFiles[i]);
threads[i] = new Thread(appender);
threads[i].start();
appender.run();
}
for (Thread thread : threads) {
thread.join();
}
long stopTime = System.currentTimeMillis();
System.out.println(stopTime - startTime);
}
}
class Appender implements Runnable {
private String result;
private int[] input;
private File outputFile;
public Appender(int[] input, File outputFile) {
this.result = "";
this.input = input;
this.outputFile = outputFile;
}
public void appendString() {
for (int number : input) {
this.result += String.valueOf(number);
}
try (BufferedWriter writer = new BufferedWriter(new FileWriter(this.outputFile));) {
writer.write(this.result);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
appendString();
}
}以毫秒为单位测量的执行时间是多线程在3600-3700之间,单线程在2800-2900之间。与我的预期完全相反,因为所有线程都在不同的数组上工作,并在不同的文件中写入。
发布于 2018-12-22 18:53:16
简而言之,多线程本身并不会加速一切。实际上,它会使某些事情变慢;我还没有分析您的代码,但您可能已经在示例中向您自己展示了这一点。
为了让单处理器计算机执行多线程,它在时间片中工作;它在一个片上工作一段时间,然后在另一个片上工作一段时间,等等。即使在单处理器计算机上,这在桌面UI等情况下也有很大的优势,在桌面UI中,您希望鼠标光标和键盘按钮继续为用户响应,同时程序还可以做其他事情。
但是,如果您的程序是“计算受限的”,也就是说,如果程序速度的限制因素是处理器可以执行的速度,那么在单处理器示例中,多线程不会有任何好处。这两个线程不能同时执行,因此在代码中使用多线程只会增加维护有关时间片的信息以及在时间片之间切换的开销。
多线程在代码花费一些时间等待I/O时也有很大的好处。一个线程可以获取输入,将该输入交给另一个线程进行处理,然后在循环中返回以获取更多的输入。在单处理器机器上没有多线程的情况下,等待I/O所花费的时间不允许完成任何处理,而多线程将允许计算继续进行。
在多处理器机器上,情况会有所不同(也更复杂);您没有提到您在处理器方面的情况,但我希望这足以让您开始了解正在发生的事情。
发布于 2018-12-22 19:12:22
您的代码不进行计算,它只是将静态数据复制到文件中。您肯定是磁盘I/O受限的,而不是CPU受限的。
同时写入多个文件是一种悲观看法;在顺序模式下,磁盘I/O最快(在HDD上,最大限度地减少磁头移动;在SSD上,写入大块比写入小块快)。
一旦你达到了计算数据比存储数据慢的地步,那么你将从并行计算部分(而不是存储部分)中受益。
发布于 2018-12-22 19:28:22
感谢大家的回答!我从他们身上学到了很多!我的代码中的问题是有一行本不应该出现的代码。goughy000让我大开眼界,我不应该调用appender.run()方法,因为thread.start()调用了它。现在多线程时间降到了1800-1900ms。
https://stackoverflow.com/questions/53894924
复制相似问题