Раздвижное окно с 50% -ным перекрытием с нитями производителя / потребителя
У меня есть следующий сценарий в Java:
- 1 поток производителей сохраняет объекты событий в очереди. Блокировка это не вариант. Он всегда должен хранить каждый элемент в конце очереди и выходить (поэтому никаких ограниченных очередей).
- 1 потребительский поток ожидает, пока в очереди будет количество событий WINDOW_SIZE. Затем он должен извлечь все события WINDOW_SIZE из очереди для обработки, но удалить только половину из них (то есть WINDOW_SIZE/2), для перекрытия на 50%.
Мой вопрос: какую (параллельную) коллекцию вы бы использовали для эффективной реализации этого? События приходят с частотой 100 Гц на устройстве с ограниченными ресурсами (мобильный телефон под управлением Android). Я подумал об использовании следующего, ни один из которых, кажется, не подходит:
- ConcurrentLinkedQueue, проверяющий размер очереди при каждом его изменении и использующий peek()/poll() в приемнике, когда доступны события WINDOW_SIZE. Это кажется немного громоздким.
- 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 и не передает его в очередь после заполнения?