我想做一个我已经完成的任务,除了这次使用多线程。我必须从文件中读取大量数据(逐行),从每行中获取一些信息,然后将其添加到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将成为主要瓶颈,因此并行化这一点几乎没有效率优势。但是,出于演示目的,我是否正走在正确的轨道上?不知道如何使用多线程,我仍然有点困扰。
答案 0 :(得分:6)
为什么需要多个线程?你只有一个磁盘,它只能这么快。几乎可以肯定,多线程在这种情况下无济于事。如果确实如此,从用户的角度来看,它将是非常小的。多线程不是你的问题。从一个巨大的档案中读取是你的瓶颈。
答案 1 :(得分:2)
I / O通常比内存中的任务花费更长的时间。我们称之为 I / O-bound 这样的工作。并行性最多可能会有微小的改善,实际上可能会使事情变得更糟。
您当然不需要使用其他线程将某些内容放入地图中。除非你的解析非常昂贵,否则你也不需要一个不同的线程。
如果你有其他线程来完成这些任务,他们可能会花大部分时间坐在那里等待下一行阅读。
即使并行化I / O也不一定有帮助,也可能会受到伤害。即使您的CPU支持并行线程,您的硬盘驱动器也可能不支持并行读取。
修改强>
我们所有评论此事的人都认为这项任务可能是I / O限制的 - 因为这种情况经常发生。但是,从下面的评论中,这个案例被证明是一个例外。一个更好的答案将包括下面的第四个评论:
测量读取文件中所有行而不处理它们所花费的时间。比较读取和处理它们所花费的时间。这将给你一个松散的上限,你可以节省多少时间。这可能会因线程同步的新成本而降低。
答案 2 :(得分:0)
您可能希望阅读Amdahl's Law。由于您的大多数工作都是严格连续的(IO),因此通过多线程化其余部分可以获得微不足道的改进。当然不值得创建不漏水的多线程代码。
也许你应该寻找一个新的玩具示例来并行化。