为什么在Java

时间:2018-12-22 10:40:30

标签: java multithreading

我是多线程新手,今天我尝试在相同条件下运行多线程与单线程程序的一些性能测试。令我惊讶的是,我发现单线程选项的工作速度比多线程选项快。那可能是什么原因?

我编写了一个简单的程序,该程序带有字符串叠加类,将结果写入文件中。我创建了5个50000零和5个输出文件的数组,这些数组在for循环中传递给Appender类的构造函数。在多线程选项中,我调用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的单线程。完全与我的预期相反,因为所有线程都在不同的数组上工作并写入不同的文件。

4 个答案:

答案 0 :(得分:1)

简短的回答是,多线程本身并不能加快一切。实际上,它会使某些事情变慢。我尚未分析您的代码,但您可能已在示例中向您证明了这一点。

为了使单处理器计算机执行多线程处理,它会按时间“切片”工作;它在一个切片上工作一段时间,然后在另一个切片上工作一段时间,依此类推。即使在单处理器计算机上,这在桌面UI这样的情况下也具有很大的优势,在这种情况下,您希望鼠标光标和键盘按钮能够继续响应用户的请求,而程序同时还执行其他操作。

但是,如果您的程序是“计算绑定”的,也就是说,如果程序速度的限制因素是处理器可以执行的速度,那么多线程将无济于事在单处理器示例中。这两个线程无法同时执行,因此在代码中通过多线程进行的所有操作都会增加维护有关时间片的信息以及在时间片之间进行切换的开销。

在代码花费一些时间等待I / O的情况下,多线程也可以带来很多好处。一个线程可以获取输入,将该输入交给另一个线程进行处理,然后返回一个循环以获取更多输入。如果没有在单处理器计算机上使用多线程,那么等待I / O所花费的时间将无法完成任何处理,而多线程将使计算得以继续。

在多处理器机器上,它变得不同(并且更加复杂);您没有提到处理器方面的情况,但是我希望这足以让您开始了解正在发生的事情。

答案 1 :(得分:1)

您的代码不进行计算,仅将静态数据复制到文件中。您肯定是受磁盘I / O约束的,而不是受CPU约束的。

同时写入多个文件是一种悲观。磁盘I / O在顺序模式下最快(在HDD上最大程度地减少磁头移动,在SSD上写大块比写小块快)。

一旦计算数据的速度慢于存储数据的速度,然后您将受益于并行化计算部分(而不是存储部分)。

答案 2 :(得分:0)

根据Oracle关于进程和线程的Java™教程here,其中提到:

  

线程共享进程的资源,包括内存和开放   文件。这样可以提高效率,但可能会出现问题,   交流。

正如arcy在他的回答中提到的那样,有很多因素会影响多线程环境的执行。

答案 3 :(得分:0)

感谢大家的回答!我从他们那里学到了很多东西!我的代码中的问题是不应存在的一行代码。 goughy000让我睁开了眼睛,我不应该调用appender.run()方法,因为thread.start()会调用它。现在多线程时间下降到1800-1900毫秒。