Java中的生产者/消费者:保持平衡

时间:2016-10-26 13:19:25

标签: java multithreading producer-consumer

我在Java中有一个文本处理应用程序,它通过块(~100000行)读取文件块并在单独的线程中处理每个块。

效果很好,但有一个问题。读取行比处理它们要快得多,程序最终会有一个Runnables队列等待轮到他们。这需要一些我打算保存的记忆。

我希望程序能够采用这种方式:

  • 阅读16个块并将其提交给8个runnables;
  • 如果未处理的块数低于12,则再读取4块文本。

这将使Runnables忙,但同时保留内存以进行处理(而不是存储块)。

我如何用Java做到这一点?写在preudocode我想要这个:

loop {

  chunk = readChunkOfData();

  counter.inc();    

  processAsync(chunk);

  if (counter.isBiggerThan(16)) {
    counter.sleepWhileCounterIsBiggerThan(12);
  }
}

...

worker {
  // do the job

  counter.dec();
}

1 个答案:

答案 0 :(得分:1)

正如Marko Topolnik评论的那样,使用有界(阻塞)queues可以优雅地解决您的问题。

你不需要计数器,因为队列知道它的限制,你的伪代码最终会看起来像下面这样

loop {
    chunk = readChunkOfData();
    queue.put(chunk);
}

worker {
    chunk = queue.take();
    process(chunk);
}

这假设队列是例如new ArrayBlockingQueue(16);并且由所有工作人员共享。您还可以使用工作中的drainTo(Collection<? super E> c, int maxElements)一次性获取多个块,作为工作方的额外工作缓冲区,但这可能不会产生太大影响。