我有一个wordCount(CharacterReader charReader)
函数,它接受一个字符流,将它们转换为单词。
我还有一个Collection<CharacterReader> characerReaders
,包含多个字符流。集合中的读者数量可能会有所不同,我想从所有流中读取并计算所有单词。
我对线程有点困惑,找不到任何类似的例子。 我基本上希望多个线程将他们的单词输出到SortedMap,这样我就可以实时计算总字数。
我将如何做到这一点?
由于
答案 0 :(得分:2)
ConcurrentSkipListMap
SortedMap
和ConcurrentMap
。CharacterReader
创建一个调用Runnable
函数的wordCount
(访问前面描述的映射)。 Runnable
后,您可以创建ExecutorService
(例如使用Executors.newCacheThreadPool()
),将其全部传递给Runnable
并等待它们完成(请参阅类ExecutorService
的{{3}}中的示例。)您也可以在将Runnable
发送到ExecutorService
之前创建{{1}}。
答案 1 :(得分:1)
创建一个WordMap
类,它封装您的有序地图,并确保所有对地图的访问都已正确同步。或者使用已经是线程安全的并发映射。
创建此类的实例。使用Executors类创建具有所需特征的ExecutorService
。
然后遍历集合,并为每个读者创建一个Callable
或Runnable
填充WordMap实例,其中包含此阅读器中的单词,并提交此Callable
或{ {1}} Runnable
。
答案 2 :(得分:1)
vainolo和JB的答案都很好。
我将添加一个内容,即描述如何建立高度并发的数据结构来存储您的字数。
正如vainolo所说,ConcurrentSkipListMap是你想要的基本数据结构,因为它既有排序又有并发。为了好好利用它,你想避免做任何锁定。这意味着您必须避免涉及锁定 - 读 - 写 - 解锁周期的模式。这有两个结果:首先,在地图中添加一个新单词不应该涉及锁定,并且增加现有单词的计数不应该涉及锁定。
您可以使用ConcurrentMap的putIfAbsent方法安全地向地图添加新内容。然而,仅凭这一点还不够,因为每次使用它时都必须提供潜在的价值,这可能很昂贵。最简单的方法是使用一种双重检查的锁定模式,你首先只是尝试获取一个现有值,然后如果你发现没有一个,用putIfAbsent添加一个新模式(你不能简单地call put,因为两个线程之间可能会同时发生竞争。)
通过不在地图中存储整数,而不是在整数中包含整数的对象,可以轻松地进行无锁定的增量。这样,您就不必在地图中添加增量值,只需增加已存在的对象即可。 AtomicInteger似乎是一个很好的候选人。
把它们放在一起,你得到:
public class WordCounts {
private final ConcurrentMap<String, AtomicInteger> counts
= new ConcurrentSkipListMap<String, AtomicInteger>();
public void count(String word) {
AtomicInteger count = getCount(word);
count.incrementAndGet();
}
private AtomicInteger getCount(String word) {
AtomicInteger count = counts.get(word);
if (count == null) {
AtomicInteger newCount = new AtomicInteger();
count = counts.putIfAbsent(word, newCount);
if (count == null) count = newCount;
}
return count;
}
}