如何有效地使用多线程

时间:2013-07-30 20:52:09

标签: java multithreading

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

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

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将成为主要瓶颈,因此并行化这一点几乎没有效率优势。但是,出于演示目的,我是否正走在正确的轨道上?不知道如何使用多线程,我仍然有点困扰。

3 个答案:

答案 0 :(得分:6)

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

答案 1 :(得分:2)

I / O通常比内存中的任务花费更长的时间。我们称之为 I / O-bound 这样的工作。并行性最多可能会有微小的改善,实际上可能会使事情变得更糟。

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

如果你有其他线程来完成这些任务,他们可能会花大部分时间坐在那里等待下一行阅读。

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

修改

我们所有评论此事的人都认为这项任务可能是I / O限制的 - 因为这种情况经常发生。但是,从下面的评论中,这个案例被证明是一个例外。一个更好的答案将包括下面的第四个评论:

  

测量读取文件中所有行而不处理它们所花费的时间。比较读取和处理它们所花费的时间。这将给你一个松散的上限,你可以节省多少时间。这可能会因线程同步的新成本而降低。

答案 2 :(得分:0)

您可能希望阅读Amdahl's Law。由于您的大多数工作都是严格连续的(IO),因此通过多线程化其余部分可以获得微不足道的改进。当然不值得创建不漏水的多线程代码。

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