0

我想做一个我已经完成的任务,除了这次使用多线程。我必须从文件中读取大量数据(逐行),从每一行中获取一些信息,然后将其添加到地图中。该文件超过一百万行,因此我认为它可能会受益于多线程。

我不确定我在这里的方法,因为我以前从未在 Java 中使用过多线程。我想让 main 方法进行读取,然后将已读取的行提供给另一个线程,该线程将格式化字符串,然后将其提供给另一个线程以放入映射中。

public static void main(String[] args)
{
    //Some information read from file
    BufferedReader br = null;
    String line = '';
    try {
        br = new BufferedReader(new FileReader("somefile.txt"));
        while((line = br.readLine()) != null) {
            // Pass line to another task
        }


    // Here I want to get a total from B, but I'm not sure how to go about doing that

}


public class Parser extends Thread
{
    private Mapper m1;

    // Some reference to B
    public Parse (Mapper m) {
        m1 = m;
    }

    public parse (String s, int i) {
        // Do some work on S
        key = DoSomethingWithString(s);
        m1.add(key, i);
    }

}

public class Mapper extends Thread
{
    private SortedMap<String, Integer> sm;
    private String key;
    private int value;
    boolean hasNewItem;

    public Mapper() {
        sm = new TreeMap<String, Integer>;
        hasNewItem = false;
    }

    public void add(String s, int i) {
        hasNewItem = true;
        key = s;
        value = i;
    }

    public void run() {
        while (!Thread.currentThread().isInterrupted()) {
            try {
                if (hasNewItem) {
                    // Find if street name exists in map
                    sm.put(key, value);
                    newEntry = false;
                }   
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        // I'm not sure how to give the Map back to main. 
    }
}

我不确定我是否采取了正确的方法。我也不知道如何终止 Mapper 线程并在 main 中检索地图。我将有多个 Mapper 线程,但我只在上面的代码中实例化了一个。

我也刚刚意识到我的 Parse 类不是一个线程,而只是另一个类,如果它没有覆盖 run() 方法,所以我认为 Parse 类应该是某种队列。

和想法?谢谢。

编辑:感谢所有的答复。似乎由于 I/O 将成为主要瓶颈,因此并行化几乎不会提高效率。但是,出于演示目的,我是否走在正确的轨道上?我仍然对不知道如何使用多线程感到有些困扰。

4

3 回答 3

6

为什么需要多个线程?你只有一个磁盘,它只能走这么快。几乎可以肯定,多线程在这种情况下无济于事。如果是这样,从用户的角度来看,这将是非常小的。多线程不是你的问题。从一个巨大的文件中读取是你的瓶颈。

于 2013-07-30T20:56:08.127 回答
2

通常 I/O 会比内存中的任务花费更长的时间。我们将此类工作称为I/O-bound。并行性充其量可能只有边际改进,实际上会使事情变得更糟。

您当然不需要其他线程来将某些内容放入地图中。除非您的解析异常昂贵,否则您也不需要其他线程。

如果您有其他线程来处理这些任务,他们可能会花费大部分时间坐在那里等待读取下一行。

即使并行化 I/O 也不一定有帮助,而且可能会受到伤害。即使您的 CPU 支持并行线程,您的硬盘驱动器也可能不支持并行读取。

编辑:

我们所有对此发表评论的人都认为该任务可能是 I/O 绑定的——因为这通常是正确的。但是,从下面的评论来看,这个案例是个例外。更好的答案将包括下面的第四条评论:

测量读取文件中所有行而不处理它们所需的时间。比较阅读和处理它们所需的时间。这将为您提供一个可以节省多少时间的宽松上限。这可以通过线程同步的新成本来减少。

于 2013-07-30T20:55:54.517 回答
0

您不妨阅读阿姆达尔定律。由于您的大部分工作都是严格串行的(IO),因此通过多线程处理其余部分,您将获得微不足道的改进。当然不值得花费创建防水多线程代码的成本。

也许您应该寻找一个新的玩具示例来并行化。

于 2013-07-30T23:07:53.570 回答