用Java浏览文件

时间:2011-02-24 14:49:03

标签: java multithreading

我希望用Java读取文件的内容。我有大约8000个文件来读取内容并将其放在HashMap中(路径,内容)。我认为使用Threads可以选择这样做来加快这个过程。 据我所知,所有8000个文件都在不同的线程中读取它们的内容是不可能的(我们可能想限制线程),对它有何评论?另外我是Java新手中的新手,有没有人可以帮忙开始这个呢?

到目前为止,我认为这个pesudo代码:

    public class ThreadingTest extends Thread {

public HashMap<String, String > contents = new HashMap<String, String>();


public ThreadingTest(ArrayList<String> paths)
{
    for(String s : paths)
    {
      // paths is paths to files.
      // Have threading here for each path going to get contents from a        
      //  file  
        //Not sure how to limit and start threads here
        readFile(s);
        Thread t = new Thread();
        t.start();
    }
}


public String readFile(String path) throws IOException
{
    FileReader reader = new FileReader(path);
    StringBuilder sb = new StringBuilder();
    BufferedReader br = new BufferedReader(reader);
    String line;
    while ( (line=br.readLine()) != null) {
      sb.append(line);
    }

    return textOnly;

}

 }

完成线程处理的任何帮助。谢谢

6 个答案:

答案 0 :(得分:7)

简答:按顺序读取文件。磁盘I / O不能很好地并行化。

长答案:如果磁盘擅长随机访问(SSD磁盘)或者文件放在多个不同的磁盘上,线程可能会提高读取性能,但如果它们不是你,你可能最终会遇到大量缓存未命中并等待磁盘寻找正确的读取位置。 (即使你的磁盘擅长随机访问,你仍然可能会在那里结束。)

如果您想衡量而不是猜测,请使用Executors.newFixedThreadPool创建一个ExecutorService,它可以并行读取您的文件。尝试不同的线程数,但如果每个物理磁盘的一个读取器线程为您提供最佳性能,请不要感到惊讶。

答案 1 :(得分:1)

这是线程池的典型任务。请参阅此处的教程:http://download.oracle.com/javase/tutorial/essential/concurrency/pools.html

答案 2 :(得分:1)

import java.io.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.*;

public class PooledFileProcessing {
    private Map<String, String> contents = Collections.synchronizedMap(new HashMap<String, String>());
    //  Integer.MAX_VALUE items max
    private LinkedBlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>();

    private ExecutorService executor = new ThreadPoolExecutor(
            5,  //  five workers by default
            20, //  up to twenty workers
            1, TimeUnit.MINUTES,    //  idle thread dies in one minute
            workQueue
    );

    public void process(final String basePath) {
        visit(new File(basePath));
        System.out.println(workQueue.size() + " jobs still in queue");
        executor.shutdown();
        try {
            executor.awaitTermination(5, TimeUnit.MINUTES);
        } catch (InterruptedException e) {
            System.out.println("interrupted while awaiting termination");
        }
        System.out.println(contents.size() + " files indexed");
    }

    public void visit(final File file) {
        if (!file.exists()) {
            return;
        }

        if (file.isFile()) {    //  skip the dirs
            executor.submit(new RunnablePullFile(file));
        }

        //  traverse children
        if (file.isDirectory()) {
            final File[] children = file.listFiles();
            if (children != null && children.length > 0) {
                for (File child : children) {
                    visit(child);
                }
            }
        }
    }

    public static void main(String[] args) {
        new PooledFileProcessing().process(args.length == 1 ? args[0] : System.getProperty("user.home"));
    }

    protected class RunnablePullFile implements Runnable {
        private final File file;

        public RunnablePullFile(File file) {
            this.file = file;
        }

        public void run() {
            BufferedReader reader = null;
            try {
                reader = new BufferedReader(new FileReader(file));
                StringBuilder sb = new StringBuilder();
                String line;
                while (
                        (line=reader.readLine()) != null &&
                        sb.length() < 8192 /* remove this check for a nice OOME or swap thrashing */
                ) {
                  sb.append(line);
                }

                contents.put(file.getPath(), sb.toString());
            } catch (IOException e) {
                System.err.println("failed on file: '" + file.getPath() + "': " + e.getMessage());
                if (reader != null) {
                    try {
                        reader.close();
                    } catch (IOException e1) {
                        //  ignore that one
                    }
                }
            }
        }
    }
}

答案 3 :(得分:0)

根据我的经验,线程有帮助 - 使用线程池并使用每个核心大约1..2个线程的值。

请注意哈希映射 - 考虑仅通过同步方法将数据放入地图。我记得我曾经在类似的项目中遇到过一些丑陋的问题,它们与中央哈希映射的并发修改有关。

答案 4 :(得分:0)

只是一些快速提示。

首先,为了让您开始使用线程,您应该只查看Runnable接口或Thread类。要创建一个线程,您必须使用类实现此接口,或者使用另一个类扩展此类。你也可以创建匿名线程,但我不喜欢那些可读性,除非它的东西超简单。

接下来,只是关于使用多个线程处理文本的一些注意事项,因为它恰好发生了我有一些经验!请记住,如果文件很大并且需要相当长的时间来处理您希望监视CPU的单个文件。根据我的经验,我在处理时进行了大量的计算和查找,这极大地增加了我的负载,所以最后我发现我只能创建与处理器一样多的线程,因为每个线程都是如此劳动密集。所以记住这一点,你想要监控每个线程对处理器的影响。

答案 5 :(得分:0)

如果所有文件都在同一个物理磁盘上,我不确定是否有线程可以真正加快进程。它甚至可以减慢速度,因为磁盘必须不断地从一个位置切换到另一个位置。