10

我有一个非常大的 CSV 文件(1GB+),它有 100,000 行。

我需要编写一个 Java 程序来解析 CSV 文件中的每一行,以创建一个用于发送 HTTP 请求的正文。

换句话说,我需要发送 100,000 个与 CSV 文件中的行相对应的 HTTP 请求。如果我在一个线程中执行这些操作会很长。

我想创建 1,000 个线程来做 i) 从 CSV 文件中读取一行,ii) 创建一个 HTTP 请求,其正文包含读取行的内容,以及 iii) 发送 HTTP 请求并接收响应。

这样,我需要将 CSV 文件拆分为 1,000 个块,并且这些块之间应该没有重叠的行。

这种拆分程序的最佳方法是什么?

4

6 回答 6

12

同时在多个位置读取单个文件不会让你走得更快(但它可能会大大减慢你的速度)。

不是从多个线程读取文件,而是从单个线程读取文件,并并行处理这些行。单个线程应该逐行读取您的 CSV,并将每一行放入队列中。然后,多个工作线程应该从队列中取出下一行,对其进行解析,转换为请求,并根据需要并发处理请求。然后将由单个线程完成工作的拆分,确保没有丢失的行或重叠。

于 2012-06-19T10:20:42.613 回答
5

您可以有一个线程来读取 CSV 的行并构建读取的行列表。当这达到某个限制时,例如 100 行将其传递到固定大小的线程池以作为请求发送。

我怀疑除非您的服务器有 1000 个内核,否则您可能会发现使用 10-100 个并发请求会更快。

于 2012-06-19T10:18:48.067 回答
2

通过构造您的对象并将其传递给该行,将这一行委托给 池中的CSV一个可用行,然后将其传递给该行,该行将在单线程中读取文件,该对象将异步执行。ThreadRunnable TaskExecutors's submit()

 public static void main(String[] args) throws IOException {

      String fName = "C:\\Amit\\abc.csv";
      String thisLine;
      FileInputStream fis = new FileInputStream(fName);
      DataInputStream myInput = new DataInputStream(fis);
      ExecutorService pool=Executors.newFixedThreadPool(1000);
      int count = 0;  // Concurrent request to Server barrier

      while ((thisLine = myInput.readLine()) != null) {
          if (count > 150) {
              try {
                  Thread.sleep(100);
                  count = 0;
              } catch (InterruptedException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
              }
          }

          pool.submit(new MyTask(thisLine));
          count++;
      }

    }
}

你的任务在这里:

class MyTask implements Runnable {
      private String lLine;
      public MyTask(String line) {
           this.lLine=line;

      }

      public void run() {
          // 1) Create Request  lLine
          // 2) send the HTTP request out and receive response
      }
}
于 2012-06-19T10:30:13.773 回答
2

如果您希望在同一操作中解压缩和解析,请查看https://github.com/skjolber/unzip-csv

于 2018-08-02T00:37:43.233 回答
1

让一个线程逐行读取文件,并且对于读取的每一行,将任务发布到一个ExecutorService以执行每个任务的 HTTP 请求。

从多个线程读取文件是行不通的,因为要读取第nth 行,您必须先读取所有其他行。(如果您的文件包含固定宽度的记录,理论上它可以工作,但 CSV 不是固定宽度格式。)

于 2012-06-19T10:19:33.943 回答
0

计划于本月发布的 Java 8 将通过并行流和 lambda 改进对此的支持。Oracle 关于并行流的教程可能是一个很好的起点。

请注意,这里的一个陷阱是过多的并行性。对于检索 URL 的示例,并行调用数量较少可能是个好主意。过多的并行性不仅会影响带宽和您要连接的网站,而且还会面临文件描述符不足的风险,在大多数运行 java 的环境中,文件描述符是严格受限的资源。

一些可能对您有所帮助的框架是 Netflix 的RxJavaAkka。请注意,这些框架并非微不足道,需要一些努力才能学习。

于 2014-03-08T12:14:17.290 回答