2013-04-23 64 views
5

一直在寻找一段时间,现在我对这个问题有点困惑。我希望能够接受一个输入流并分段读取它。段不互相交互,它们只是要从上载的文件中插入或更新数据库中的值。是否可以通过设置段大小并发读取输入流,然后在转出新线程以处理转换和插入/更新之前跳过前进?Java:并发读取InputStream

本质上来说,文件是一个ID的列表(每行一个ID),尽管如果我可以指定一个分隔符会更好。某些文件可能非常庞大,所以我想要将数据处理并转换为段,以便在插入/更新数据库之后可以释放JVM内存。这可能吗?如果有的话,是否有任何图书馆已经这样做?

在欢呼声中提前致谢,

Alexei Blue。

回答

6

一个好的方法可能是让一个阅读器读取块,然后将每个块从线程池移交给工作线程。鉴于这些将被插入到数据库中,与读取输入相比,插入将是缓慢的部分,因此单个线程应该足以进行读取。

下面是一个示例,将System.in的每行处理交给工作线程处理。如果您在单个事务中执行大量插入操作,则数据库插入的性能要好得多,因此,传递一组1000行代码将比传递单行代码更好,如示例中所示。

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 

public class Main { 
    public static class Worker implements Runnable { 
     private final String line; 

     public Worker(String line) { 
      this.line = line; 
     } 

     @Override 
     public void run() { 
      // Process line here. 
      System.out.println("Processing line: " + line); 
     } 
    } 

    public static void main(String[] args) throws IOException { 
     // Create worker thread pool. 
     ExecutorService service = Executors.newFixedThreadPool(4); 

     BufferedReader buffer = new BufferedReader(new InputStreamReader(System.in)); 
     String line; 

     // Read each line and hand it off to a worker thread for processing. 
     while ((line = buffer.readLine()) != null) { 
      service.execute(new Worker(line)); 
     } 
    } 
} 
+0

嗨埃德感谢^。^所以,如果我读1000行到一个StringBuffer,然后通过这个开了个工作线程的例子/更新的数据库,你认为这会是一个好方法吗? :) – 2013-04-23 09:11:45

+0

这很可能是最好的1000行读入'列表'或'的String []'。如果你读它们放入一个'StringBuffer'那么它会是一个字符串,你需要分析出各行第二次。 – 2013-04-23 11:15:41

1

我不认为你可以同时读取InputStream。这就是合同定义读取,重置和标记的原因 - 这个想法是流在内部跟踪已读和未读的内容。

如果您正在阅读文件,只需打开多个流。您可以使用skip()方法为其他线程提前移动标记以避免重复的行处理。 BufferedReader也可能有所帮助,因为它提供了阅读line by line

+0

呀缓冲读卡器+跳过目前我做的方式,需要多一点的工作,但我敢肯定,使用单一的顺序读取和移动工作给其他线程将是一个不错的改进。欢呼的链接。 – 2013-04-23 09:09:00

1

首先,要从不同的偏移量开始同时读取文件,您需要随机访问到文件,这意味着从任何位置读取文件。 Java允许这与中的RandomAccessFile或java.in与SeekableByteChannel的java.nio中的:

Best Way to Write Bytes in the Middle of a File in Java

http://docs.oracle.com/javase/tutorial/essential/io/rafs.html

我认为对于速度的原因,你会喜欢的java.nio。 Java NIO FileChannel versus FileOutputstream performance/usefulness

现在你知道如何从任何位置读取,但你需要同时做到这一点。使用相同的文件访问对象是不可能的,因为它们保持文件中的位置。因此你需要和线程一样多的文件访问对象。既然你正在阅读不写,应该是好的。

现在你知道如何从许多不同的偏移量同时读取同一个文件。

但考虑性能。尽管线程的数量只有一个磁盘驱动器和随机读取(多线程访问同一个文件)的性能备受慢得多然后按顺序读取(一个线程读取一个文件)。即使它突袭0或1 - 无所谓。连续阅读总是快得多。所以在你的情况下,我建议你在一个线程中读取文件,并向其他线程提供来自该读线程的数据。要处理并插入

+0

干杯维塔利和感谢的链接 – 2013-04-23 09:06:01