使用多线程合并已排序的文件

时间:2017-11-23 00:20:45

标签: java multithreading sorting external-sorting

多线程对我来说是新的,所以对于错误感到抱歉。

我编写了下面的程序,它将文件与mulithreading合并,但我无法弄清楚如何管理最后一个文件,并且在一次迭代之后如何合并新创建的文件。

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.ArrayList;

public class MergerSorter extends Thread {
int fileNumber = 1;

public static void main(String[] args) {
    startMergingfiles(9);
}

public MergerSorter(int fileNum) {
    fileNumber = fileNum;
}

public static void startMergingfiles(int numberOfFiles) {
    int objectcounter = 0;

    while (numberOfFiles != 1) {
        try {
            ArrayList<MergerSorter> objectList = new ArrayList<MergerSorter>();
            for (int j = 1; j <= numberOfFiles; j = j + 2) {
                if (numberOfFiles == j) {// Last Single remaining File

                } else {
                    objectList.add(new MergerSorter(j));
                    objectList.get(objectcounter).start();
                    objectList.get(objectcounter).join();
                    objectcounter++;
                }
            }
            objectcounter = 0;
            numberOfFiles = numberOfFiles / 2;

        } catch (Exception e) {
            System.out.println(e);
        }

    }
}

public void run() {

    try {
        FileReader fileReader1 = new FileReader("src/externalsort/" + Integer.toString(fileNumber));
        FileReader fileReader2 = new FileReader("src/externalsort/" + Integer.toString(fileNumber + 1));
        BufferedReader bufferedReader1 = new BufferedReader(fileReader1);
        BufferedReader bufferedReader2 = new BufferedReader(fileReader2);

        String line1 = bufferedReader1.readLine();
        String line2 = bufferedReader2.readLine();

        FileWriter tmpFile = new FileWriter("src/externalsort/" + Integer.toString(fileNumber) + "op.txt", false);
        int whichFileToRead = 0;

        boolean file_1_reader = true;
        boolean file_2_reader = true;

        while (file_1_reader || file_2_reader) {
            if (file_1_reader == false) {
                tmpFile.write(line2 + "\r\n");
                whichFileToRead = 2;
            } else if (file_2_reader == false) {
                tmpFile.write(line1 + "\r\n");
                whichFileToRead = 1;
            } else {
                String value1 = line1.substring(0, 10);
                String value2 = line2.substring(0, 10);
                int ans = value1.compareTo(value2);
                if (ans < 0) {
                    tmpFile.write(line1 + "\r\n");
                    whichFileToRead = 1;
                } else if (ans > 0) {
                    tmpFile.write(line2 + "\r\n");
                    whichFileToRead = 2;
                } else if (ans == 0) {
                    tmpFile.write(line1 + "\r\n");
                    whichFileToRead = 1;
                }
            }

            if (whichFileToRead == 1) {
                line1 = bufferedReader1.readLine();
                if (line1 == null)
                    file_1_reader = false;
            } else {
                line2 = bufferedReader2.readLine();
                if (line2 == null)
                    file_2_reader = false;

            }
        }

        tmpFile.close();
        bufferedReader1.close();
        bufferedReader2.close();
        fileReader1.close();
        fileReader2.close();

    } catch (Exception e) {
        System.out.println(e);
    }

 }
}

我正在尝试将排序文件与多线程合并。假设我有50个文件,我想将所有这些单独的文件合并为一个最终排序的文件,但我希望通过多线程加速并利用每个核心,但我无法做到。文件很大,所以它们不能放在堆/ RAM中,所以我必须读取每个文件并继续写。

1 个答案:

答案 0 :(得分:0)

您可以使用merge sort执行此操作,但是您需要使用大量小的排序文件,而不是许多小的排序列表。将所有文件分解为小的已排序文件后,您可以再次将它们合并在一起,直到最终得到一个已排序的文件。

不幸的是,您可能无法获得高CPU利用率,因为等待磁盘I / O完成所花费的时间很多。

编辑:只需阅读您对评论的回复,这听起来就像是在合并排序的最后一步请求帮助。上面wiki链接中的图形也可以帮助您理解。因此,假设您的所有文件都已排序,请转到此处:

  1. 从每个文件中读取1个项目
  2. 找出哪个最低/最小/无论并将该行写入结果文件
  3. 从刚刚提供最后一项
  4. 的文件中读取新项目
  5. 重复步骤2和3,直到所有文件都被完全读取。