私はJavaで次のシナリオを持っています:
- 1 つのプロデューサー スレッドがイベント オブジェクトをキューに格納します。それをブロックすることはオプションではありません。常に各要素をキューの最後に格納して終了する必要があります(したがって、制限されたキューはありません)。
- 1 つのコンシューマー スレッドが、キューに WINDOW_SIZE の数のイベントが含まれるのを待ちます。次に、処理のためにキューからすべての WINDOW_SIZE イベントを取得する必要がありますが、50% のオーバーラップのために、それらの半分 (つまり、WINDOW_SIZE/2) のみを削除する必要があります。
私の質問は、これを効率的に実装するためにどの (同時) コレクションを使用するかということです。イベントは、リソースが制限されたデバイス (Android を実行している携帯電話) で 100Hz で受信されます。私は次のものを使用することを考えましたが、どれも適切に適合していないようです:
- 変更されるたびにキューのサイズをチェックし、WINDOW_SIZE イベントが利用可能な場合はコンシューマーで peek()/poll() を使用する ConcurrentLinkedQueue。これは少し面倒そうです。
- ArrayBlockingQueue、再びキュー サイズをチェックし、drainTo() を使用します。ただし、そのメソッドには次のドキュメントがあります。「[...]さらに、操作の進行中に指定されたコレクションが変更された場合、この操作の動作は未定義です。[...]」. これは、並行コレクションでは少し奇妙に思えます。
コード例を次に示します。
import java.util.Queue;
import com.google.common.collect.Queues;
public class AccelerometerProcessor implements Runnable {
private static final int WINDOW_SIZE = 128;
private final Queue<AccelerometerEvent> eventQueue = Queues.newConcurrentLinkedQueue();
@Override
public void run() {
while (!Thread.interrupted()) {
try {
synchronized (eventQueue) {
while (eventQueue.size() < WINDOW_SIZE) {
eventQueue.wait();
}
// We have WINDOW_SIZE eventQueue, start processing
}
} catch (InterruptedException e) {
// Do nothing
}
}
}
public void addAccelerometerEvent(AccelerometerEvent accelerometerEvent) {
synchronized (eventQueue) {
eventQueue.add(accelerometerEvent);
eventQueue.notifyAll();
}
}
}
ちなみにGoogle Guavaも使っているので、聞いたことのない素敵なコレクションがあれば紹介してください。
だから:これを効率的かつきれいに解決する方法はありますか?