0

私はJavaで次のシナリオを持っています:

  • 1 つのプロデューサー スレッドがイベント オブジェクトをキューに格納します。それをブロックすることはオプションではありません。常に各要素をキューの最後に格納して終了する必要があります(したがって、制限されたキューはありません)。
  • 1 つのコンシューマー スレッドが、キューに WINDOW_SIZE の数のイベントが含まれるのを待ちます。次に、処理のためにキューからすべての WINDOW_SIZE イベントを取得する必要がありますが、50% のオーバーラップのために、それらの半分 (つまり、WINDOW_SIZE/2) のみを削除する必要があります。

私の質問は、これを効率的に実装するためにどの (同時) コレクションを使用するかということです。イベントは、リソースが制限されたデバイス (Android を実行している携帯電話) で 100Hz で受信されます。私は次のものを使用することを考えましたが、どれも適切に適合していないようです:

  1. 変更されるたびにキューのサイズをチェックし、WINDOW_SIZE イベントが利用可能な場合はコンシューマーで peek()/poll() を使用する ConcurrentLinkedQueue。これは少し面倒そうです。
  2. 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も使っているので、聞いたことのない素敵なコレクションがあれば紹介してください。

だから:これを効率的かつきれいに解決する方法はありますか?

4

1 に答える 1

1

常に WINDOW_SIZE/2 イベントを一括で消費する場合、プロデューサー スレッド (1 つしかないと言った) がサイズ WINDOW_SIZE/2 の配列を埋めて、それがいっぱいになったらキューに渡さないのはなぜですか?

于 2013-01-16T10:39:18.143 に答える