从java中的大文本文件高效读写

时间:2017-11-04 08:24:36

标签: java multithreading

我有包含源目标节点和阈值的大文本文件。我将所有不同的节点存储在HashSet中,然后根据用户阈值过滤边缘并将过滤​​后的节点存储在分离的哈希集中。所以我想找到一个尽可能快地进行处理的方法。

public class Simulator {

static HashSet<Integer> Alledgecount = new HashSet<>();
static HashSet<Integer> FilteredEdges = new HashSet<>();

static void process(BufferedReader reader,double userThres) throws IOException {
     String line = null;
     int l = 0;

     BufferedWriter writer = new BufferedWriter( new FileWriter("C:/users/mario/desktop/edgeList.txt"));

     while ((line = reader.readLine()) != null & l < 50_000_000) {

            String[] intArr = line.split("\\s+");

            checkDuplicate(Integer.parseInt(intArr[1]), Integer.parseInt(intArr[2]), Alledgecount);

            double threshold = Double.parseDouble(intArr[3]);

            if(threshold > userThres) {  
                writeToFile(intArr[1],intArr[2],writer);

                checkDuplicate(Integer.parseInt(intArr[1]), Integer.parseInt(intArr[2]), FilteredEdges);
             }
        l++;   

     }

     writer.close();

}

static void writeToFile(String param1,String param2,Writer writer) throws IOException {

       writer.write(param1+","+param2);

   writer.write("\r\n");

}

图表类执行BFS并将节点写入单独的文件中。我已完成处理,不包括某些功能,时间如下。

在过程中读取了5000万行的计时()

without calling BFS(),checkDuplicates,writeAllEdgesToFile() -> 54s
without calling BFS(),writeAllEdgesToFile() -> 50s
without calling writeAllEdgesToFile() -> 1min

在过程中读取了3亿行的计时()

without calling writeAllEdges() 5 min 

2 个答案:

答案 0 :(得分:3)

读取文件不仅取决于CPU核心 对文件的IO操作将受到经典磁盘的物理限制的限制,这与CPU核心无法并行操作。

你可以做的是为IO操作提供一个线程以及其他用于数据处理的线程,但只有在数据处理足够长以使Thread为此任务创建Thread时才有意义{{{ 1}}在CPU调度方面有成本。

答案 1 :(得分:2)

使多线程Java程序正常运行可能非常棘手。它需要对同步问题等方面有一些深刻的理解。如果没有必要的知识/经验,您将很难搜索有时发生但不可靠再现的错误。

因此,在尝试多线程之前,请先找出是否有更简单的方法来实现可接受的性能:

找到花费时间的程序部分!

第一个问题:它是I / O还是CPU?看看任务管理器。您的单线程程序是否占用一个核心(例如,4核计算机上的CPU接近25%)?如果它远远低于那个,那么I / O必须是限制因素,改变你的程序可能不会有太多帮助 - 购买更快的HD。 (在某些情况下,执行I / O的软件风格可能会影响硬件性能,但这种情况很少见。)

如果是CPU,使用分析器,例如JDK中包含的JVisualVM,用于查找占用大部分运行时并考虑备选方案的方法。一个候选人可能是line.split("\\s+"),使用正则表达式。它们很慢,特别是如果表达式没有事先编译成模式 - 但这只不过是一个猜测,而探查器很可能会告诉你一些非常不同的地方。