我有以下问题,我不知道如何设计解决方案的部分内容:
我有一个大文本文件,我逐行阅读。 我需要处理每一行并更新HashMap。
AFAIK我需要一个生产者线程来读取文件中的行,并将这些行分派给一个消费者线程池。消费者线程应更新ConcurrentHashMap,然后获取新行。
我的问题是: 消费者线程如何访问ConcurrentHashMap? 如果我使用固定的线程池,生产者是否需要先将行添加到队列中,还是只需提交或执行新的消费者?
编辑: Zim-Zam是正确的;我希望消费者在完成后将结果转储到ConcurrentHashMap中。
我在主线程中创建ConcurrentHashMap,并将对它的引用传递给构造函数中的Consumers。消费者应该在其运行方法中添加或增加AtomicInteger。如何读取所有行并消费者完成后,如何在主线程中告知?
再次感谢。
答案 0 :(得分:1)
您可以让所有使用者共享生产者添加的同一队列,或者您可以为每个使用者提供生成器通过循环链表或类似数据结构访问的自己的队列,以便每个使用者的队列接收或多或少相同数量的数据(例如,如果你有3个消费者,那么生产者会将数据添加到queue1,然后是queue2,然后是queue3,然后是queue1等)。
您可以为每个消费者提供相同ConcurrentHashMap
的引用(例如,在消费者的构造函数中),否则您可以通过静态getter方法访问ConcurrentHashMap
。
答案 1 :(得分:1)
我认为你并不需要像你建议的那样使用生产者消费者队列。
只需让主队列读取文件,并为您读取的每一行创建一个相应的Runnable对象(将其视为命令)并将其放入线程池执行程序。 Runnable对象的内容只是处理该行并将结果放入concurrentHashMap
的逻辑可以使用有界或无界阻塞队列创建ThreadPoolExecutor,具体取决于您想要的行为。
在伪代码中它是这样的:
class LineHandler implements Runnable {
String line;
ConcurrentHashMap resultMap;
public LineHandler(String line, ConcurrentHashMap resultMap) {
this.line = line;
this.resultMap = resultMap;
}
@Override
public void run() {
// work on line
// update resultMap
}
}
// logic in your file reader thread, supposed to be in a loop:
while (moreLinesInFile()) {
String line = readFromFile();
threadPoolExecutor.submit(new LineHandler(line, concurrentHashMap));
}
threadPoolExecutor.shutdown();
答案 2 :(得分:0)
// in main thread
// assume consumers are in some kind of container
List<MyConsumer> consumers...
CountDownLatch latch = new CountDownLatch( consumers.size() );
for( MyConsumer c : consumers ) {
c.setLatch( latch );
c.start(); // starts asychronous, or submit to executor, whatever you're doing
}
// block main thread, optionally timing out
latch.await();
// Then in consumer when it's done it's work:
latch.countDown();
答案 3 :(得分:0)
我建议您使用BlockingQueue
来存储待处理的行。
主线程解析完文件后,主线程将poison object
作为最后一个对象放入队列,并等待awaitTermination(...)
让消费者完成。
在使用者线程中以特殊方式处理毒物对象。当主线程在等待时,处理posion对象的消费者线程会在shutdown()
ExecutorService
。{/ p>
至于消费者的结果只是将它们添加到某些线程安全容器中。生产者/消费者问题由Queue
:poll(...)
,put(...)
处理。
希望我能提供帮助