2011-12-16 78 views
0

考虑简单的Java应用程序,该应用程序应该遍历光盘中的文件树以查找文件正文中的特定模式。在文件中查找文本模式的多线程方法

想知道是否有可能使用多线程实现更好的性能,例如,当我们找到新的文件夹时,我们会在固定的ThreadPool中提交新的Runnable。可运行的任务应该遍历文件夹来找出新的文件夹等。我认为这个操作应该是IO绑定,而不是CPU绑定,所以产生新的线程不会提高性能。

它取决于硬盘类型? (hdd,... etc) 它取决于操作系统类型吗?

恕我直言,唯一可以并行的是 - 产生新的线程来解析文件内容,以找出文件正文中的模式。

什么是解决这个问题的常见模式呢?它应该是多线程还是单线程的?

+1

这肯定取决于光盘类型...寻道时间无小事(也就是说,如果你不使用SSD),所以我没有看到在这里使用多线程的优势。 考虑到了两个文件,如果你在并行阅读,操作系统将具有文件1读取,然后寻求文件2,然后从文件2读,然后...... – fge 2011-12-16 13:24:51

回答

1

您说得很对,您需要确定您的任务是CPU还是IO绑定,然后决定是否可以从多线程中获益。一般来说,磁盘操作非常慢,因此除非您需要解析和分析复杂性的数据量,否则您可能无法从多线程中获益太多。我只会写一个简单的测试 - 只是读取不在单线程中解析的文件,测量它,然后添加解析,看看它是否慢得多,然后决定。

也许好的设计是使用两个线程 - 一个读取线程读取文件并将数据放入(有界)队列,然后另一个线程(或更好地使用ExecutorService)解析数据 - 它会给你很好的分离您可以随时调整进行解析的线程数量。我不确定用多线程读取磁盘是否合理(除非你需要从多个物理磁盘读取数据)。

1

您可以做的是:实现单生产者多用户模式,其中一个线程搜索磁盘,检索文件,然后消费者线程处理它们。

你说得对,在这种情况下使用多个线程扫描磁盘不会有好处,事实上它可能会降低性能,因为磁盘每次都需要寻找下一个读取位置,所以你最终会反弹线程之间的磁盘。

2

我前一段时间做了眼前这个问题的一些实验。最后,我总结说,通过改变我访问文件的方式,我可以取得更好的改进。

这里的文件沃克我终于结束了使用:

// 4k buffer size ... near-optimal for Windows. 
static final int SIZE = 4 * 1024; 

// Fastest because a FileInputStream has an associated channel. 
private static void ScanDataFile(Hunter h, FileInputStream f) throws FileNotFoundException, IOException { 
    // Use a mapped and buffered stream for best speed. 
    // See: http://nadeausoftware.com/articles/2008/02/java_tip_how_read_files_quickly 
    FileChannel ch = f.getChannel(); 
    // How much I've read. 
    long red = 0L; 
    do { 
    // How much to read this time around. 
    long read = Math.min(Integer.MAX_VALUE, ch.size() - red); 
    // Map a byte buffer to the file. 
    MappedByteBuffer mb = ch.map(FileChannel.MapMode.READ_ONLY, red, read); 
    // How much to get. 
    int nGet; 
    // Walk the buffer to the end or until the hunter has finished. 
    while (mb.hasRemaining() && h.ok()) { 
     // Get a max of 4k. 
     nGet = Math.min(mb.remaining(), SIZE); 
     // Get that much. 
     mb.get(buffer, 0, nGet); 
     // Offer each byte to the hunter. 
     for (int i = 0; i < nGet && h.ok(); i++) { 
     h.check(buffer[i]); 
     } 
    } 
    // Keep track of how far we've got. 
    red += read; 
    // Stop at the end of the file. 
    } while (red < ch.size() && h.ok()); 
    // Finish off. 
    h.close(); 
    ch.close(); 
    f.close(); 
} 
相关问题