Являются ли обычные очереди неподходящими для использования при многопоточности в Java? - PullRequest
3 голосов
/ 14 октября 2011

Я пытаюсь добавить асинхронный вывод в мою программу.

В настоящее время у меня есть класс eventManager, который уведомляет каждый кадр о позиции любого из подвижных объектов, присутствующих в настоящее время в основном цикле (это рендеринг сцены; некоторые объекты меняются от кадра к кадру, другие статичны и присутствуют в каждый кадр). Я хочу записать состояние каждого кадра, чтобы добавить функции для воспроизведения сцены.

Это означает, что мне нужно сохранять изменяющуюся информацию от кадра к кадру и либо сохранять ее в памяти, либо записывать ее на диск для последующего поиска и анализа.

Я провел несколько временных экспериментов, и запись состояния каждого объекта в памяти увеличила время на кадр примерно на 25% (не говоря уже о возможности в конечном итоге достичь лимита памяти). Непосредственная запись каждого кадра на диск занимает (как и ожидалось) даже больше, почти вдвое дольше, чем запись всех кадров вообще.

Само собой разумеется, я хотел бы реализовать многопоточность, чтобы не терять количество кадров в секунду в моем основном цикле рендеринга, потому что процесс постоянно записывает на диск.

Мне было интересно, можно ли использовать обычную очередь для этой задачи или мне нужно что-то более выделенное, например, очереди, обсуждаемые в этом вопросе .

В моей ситуации есть только один производитель (основной поток) и один потребитель (поток, который я хочу асинхронно записывать на диск). Производитель никогда не удалит из очереди, а потребитель никогда не добавит к ней - так мне вообще нужна специализированная очередь?

Есть ли преимущество в использовании более специализированной очереди в любом случае ?

Ответы [ 3 ]

4 голосов
/ 14 октября 2011

Да, обычный Queue неуместен.Поскольку у вас есть два потока, вам нужно беспокоиться о граничных условиях, таких как пустая очередь, полная очередь (при условии, что вам необходимо ограничить ее из соображений памяти), или аномалиях, таких как видимость.

A LinkedBlockingQueue лучше всего подходит дляваше приложение.Методы put и take используют разные блокировки, поэтому у вас не возникнет конфликт блокировок.Метод take автоматически блокирует запись потребителя на диск, если он каким-то волшебным образом догоняет производителей, рендеринг кадров.

3 голосов
/ 14 октября 2011

Похоже, вам не нужна особая очередь, но если вы хотите, чтобы поток, удаляющий из очереди, ждал, пока что-то получится, попробуйте BlockingQueue. Он находится в пакете java.util.concurrent, поэтому он точно безопасен для потоков. Вот некоторые соответствующие цитаты с этой страницы:

A Queue, который дополнительно поддерживает операции, ожидающие очередь стать непустым при извлечении элемента и ждать места для стать доступным в очереди при хранении элемента.

...

BlockingQueue реализации предназначены для использования в основном для очереди производителя-потребителя, но дополнительно поддерживают Collection интерфейс.

...

BlockingQueue реализации являются поточно-ориентированными.

Пока вы уже профилируете свой код, попробуйте добавить туда BlockingQueue и посмотрите, что получится!

Удачи!

2 голосов
/ 14 октября 2011

Я не думаю, что это будет иметь большое значение.

Если у вас есть 25% -ная накладная нагрузка сериализации состояния в памяти, это все равно будет с очередью.Диск будет еще дороже.Механизм блокировки очередей будет сравнительно дешевым.

Одна вещь, на которую нужно обратить внимание, - это рост вашей очереди из-под контроля: диск медленный, несмотря ни на что, если он не может потреблять события очереди достаточно быстро, вы находитесь вбеда.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...