私はこのパターンを繰り返していることに気づき、Javaで慣用的なものなのか、それともこの動作を実現するためのより良い方法があるのかとよく考えました。
問題:プロデューサー/コンシューマーの設定を考えると、コンシューマーはアイテムのバッチを処理したいので、を使用しますがdrainTo()
、drainTo()
既存のアイテムをポーリングし、アイテムを取得できない可能性があります。これを回避するために、ドレインの前にatake()
を付けて、少なくとも1つのアイテムが利用可能です。
特定のデータセットで私が得る問題の1つは、バッチサイズが(1、N、1、N)の間で交互に不規則になることが多いという多くのユースケースです。一般に、これはこの問題を解決するための一般的な方法です。
例:
ArrayBlockingQueue<Foo> queue;
function void produce() {
while(true) {
queue.put(createFoo());
}
}
function void consumeBatchSpin() {
while(true) {
List<Foo> batch = Lists.newLinkedList();
queue.drainTo(batch);
doSomething(batch);
//the problem here is that if nothing is being produced, this loop will spin
}
}
function void consumeBatchTake() {
while(true) {
List<Foo> batch = Lists.newLinkedList();
batch.add(queue.take()); //force at least one item to be there
queue.drainTo(batch);
doSomething(batch);
}
}