我有一个 producer ,可以从磁盘读取文本块。多个消费者正在对该块进行计算。
如果当前要计算的 n 个块更多,我希望生产者暂停从磁盘读取数据。
已将其放在伪代码中以说明我想要实现的目标。
// "produceBlocks" reads blocks from disk one by one
// and feeds them to lambda
produceBlocks(block -> {
// (!) if activeCounter exceeds a THRESHOLD, then pause
executorService.submit(() -> {
activeCounter.incrementAndGet();
// do some work
activeCounter.decrementAndGet();
});
});
答案 0 :(得分:3)
我将为线程池使用固定长度的队列,并实现RejectedExecuptionHandler以便在当前线程中运行或暂停并重试。
例如
这是我有效使用的最后一个选项,并且在配置ExecutorService后不需要额外的代码。
答案 1 :(得分:1)
“如果当前正在计算n个以上的块,我希望生产者暂停从磁盘读取数据。”
实际的任务描述略有不同:生产者在从磁盘读取数据之前应获得许可。。
如果您的生产者是线程,则管理许可证的自然设施是Semaphore。最初它包含n个许可。生产者要读取一个块,请向Semaphore::aquire
授予1个许可。消费者处理该块时,消费者使用Semaphore::release
释放1个许可。
另一种方法是将区块和许可结合在一起。与从生产者到使用者的输出队列类似,为块创建一个输入阻塞队列。最初放置n个块。生产者要读取一个块,首先要从该队列中取出下一个块。使用者处理完一个块后,将其返回到输入队列。