我正在尝试在我的代码中使用队列。关键是我希望它打印出文件中Word的总量,这意味着我需要它在完成后将所有结果一起添加。
目前,我的程序所做的是,我有一个运行文件的阅读器,并返回一个包含文件名称及其中单词数量的字符串。然后我使用我的main方法为args数组中给出的每个参数运行for循环。每当我们通过一个新文档检查有多少单词时,我们就会把它作为一个新的主题。
public static void main(final String[] args) {
Thread t = null;
if (args.length >= 1) {
String destinationFileName = args[(args.length-1)];
for (int l = 0; l < (args.length); l++) {
final int q = l;
final Thread y = t;
Runnable r = new Runnable() {
public void run() {
String res = readTextFile(args[q]);
System.out.println(res);
}
};
t = new Thread(r);
t.start();
}
} else {
System.err.println("Not enough input files");
}
}
那么,我如何建立一个以某种方式使他们彼此等待的队列,这样就不会错误地在同一时间添加结果呢?
答案 0 :(得分:0)
此处似乎不需要阻塞队列。只需让每个线程将其结果添加到线程安全列表中,该列表可以像这样构造:
final List<String> results =
Collections.synchronizedList(new ArrayList<String>());
接下来,您希望在聚合结果之前等待所有线程完成。您可以通过在每个线程上调用join
来完成此操作。将每个线程添加到名为threads
的列表中,然后一旦所有线程都已启动,请调用:
for(Thread t : threads) {
t.join();
}
此代码将有效地等待每个线程完成后再继续。
答案 1 :(得分:0)
这是一个非常常见的例子,当需要多个线程来处理IO操作,比如从磁盘读取文件时,我想这是用于辅导的目的,对于现实生活中的例子,考虑查看地图缩减框架,如Hadoop
了解如何使用hadoop here
完成类似的任务但是,遵循一个伪示例:
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
class ConsumerProducer implements Runnable {
private final BlockingQueue<String> map;
private final BlockingQueue<Map<String, Integer>> reduce;
ConsumerProducer(BlockingQueue<String> map,
BlockingQueue<Map<String, Integer>> reduce) {
this.map = map;
this.reduce = reduce;
}
public void run() {
try {
while (true) {
Map<String, Integer> wordToOccurrences = this.consume(map
.take());
this.produce(wordToOccurrences);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void produce(Map<String, Integer> wordToOccurrences)
throws InterruptedException {
reduce.put(wordToOccurrences);
}
public Map<String, Integer> consume(String fileName) {
// read the file and return 'word' -> number of occurrences
return new HashMap<String, Integer>();
}
}
class Setup {
public static void main(String[] args) throws InterruptedException {
BlockingQueue<String> map = new LinkedBlockingQueue<String>();
BlockingQueue<Map<String, Integer>> reduce = new LinkedBlockingQueue<Map<String, Integer>>();
for (String fileName : args) {
map.put(fileName);
// assuming every thread process single file, for other options see
// http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html
ConsumerProducer c = new ConsumerProducer(map, reduce);
new Thread(c).start();
}
for (int i = 0; i < args.length; i++) {
Map<String, Integer> wordToOccurrences = reduce.take();
// start consuming results
}
// print merged map of total results
}
}