我有一个生产者-消费者场景,其中生产者的生产速度比消费者能够消费的速度快得多。通常的解决方案是使生产者阻塞,因为生产者/消费者场景的操作速度与最慢的组件一样快。限流或阻止生产者不是好的解决方案,因为我们的应用程序提供足够的时间让消费者稍后赶上。
以下是我们应用程序中完整“阶段”的示意图,与更常见的情况进行对比:
Our Application Common Scenario
2N +--------+--------+
|PPPPPPPP|oooooooo| P = Producer
|PPPPPPPP|oooooooo| C = Consumer
N +--------+--------+ N +--------+--------+--------+ o = Other Work
|CPCPCPCP|CCCCCCCC| |CPCPCPCP|CPCPCPCP|oooooooo| N = number of tasks
|CPCPCPCP|CCCCCCCC| |CPCPCPCP|CPCPCPCP|oooooooo|
------------------- ----------------------------
0 T/2 T 0 T/2 T 3T/2
这里的思路是通过不阻碍生产者来最大化吞吐量。
我们的任务操作的数据很容易进行序列化,所以我计划实现一个文件系统解决方案,用于溢出所有无法立即满足的任务。
我正在使用Java的ThreadPoolExecutor和一个具有最大容量的BlockingQueue,以确保我们不会耗尽内存。问题在于实现这样一个“分层”队列,其中可以在内存中排队的任务会立即完成,否则数据将在磁盘上排队。
我想出了两个可能的解决方案:
1.从头开始实现一个BlockingQueue,使用LinkedBlockingQueue或ArrayBlockingQueue实现作为参考。这可能就像复制标准库中的实现并添加文件系统读/写一样简单。
2.继续使用标准的BlockingQueue实现,实现一个单独的FilesystemQueue用于存储我的数据,并使用一个或多个线程来出列文件、创建Runnable并使用ThreadPoolExecutor排队它们。
这些方法是否合理?还有更好的方法吗?