Раздвижное окно с 50% -ным перекрытием с нитями производителя / потребителя

У меня есть следующий сценарий в Java:

  • 1 поток производителей сохраняет объекты событий в очереди. Блокировка это не вариант. Он всегда должен хранить каждый элемент в конце очереди и выходить (поэтому никаких ограниченных очередей).
  • 1 потребительский поток ожидает, пока в очереди будет количество событий WINDOW_SIZE. Затем он должен извлечь все события WINDOW_SIZE из очереди для обработки, но удалить только половину из них (то есть WINDOW_SIZE/2), для перекрытия на 50%.

Мой вопрос: какую (параллельную) коллекцию вы бы использовали для эффективной реализации этого? События приходят с частотой 100 Гц на устройстве с ограниченными ресурсами (мобильный телефон под управлением Android). Я подумал об использовании следующего, ни один из которых, кажется, не подходит:

  1. ConcurrentLinkedQueue, проверяющий размер очереди при каждом его изменении и использующий peek()/poll() в приемнике, когда доступны события WINDOW_SIZE. Это кажется немного громоздким.
  2. ArrayBlockingQueue, снова проверяющий размер очереди и использующий dumpTo(). Однако этот метод имеет следующую документацию: "[...] Кроме того, поведение этой операции не определено, если указанная коллекция была изменена во время выполнения операции. [...]". Это кажется немного странным для одновременной коллекции.

Вот пример кода:

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, так что, если там есть замечательная коллекция, о которой я еще не слышал, напишите мне.

Итак: Есть хорошие идеи, как решить это эффективно и чисто?

1 ответ

Решение

Если вы всегда собираетесь использовать события WINDOW_SIZE/2 в блоке, почему поток производителя (вы сказали, что он только один) не заполняет массив размером WINDOW_SIZE/2 и не передает его в очередь после заполнения?

Другие вопросы по тегам