сменная рабочая очередь - PullRequest
4 голосов
/ 11 марта 2009

Для этого есть имя, но я не знаю, что это такое, так что трудно гуглить.

Я ищу что-то в утилитах параллелизма java, которые представляют собой пару очередей, «ожидающую» очередь, используемую производителем, и очередь «обработки», используемую потребителем, где потребитель может поменяться местами. очереди атомарно. При использовании таким способом (1 поток производителя, 1 поток потребителя) отдельные очереди не должны быть потокобезопасными, только ссылки на них.

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

edit: Я думаю, что примитив, который я ищу, - это пара атомных ссылок, которые можно обменять атомно. (И я могу добавить очереди самостоятельно.)


edit 2: @ Алекс Миллер ответил на мучительный вопрос о том, о чем я думал, но не мог вспомнить. Однако это не решает мою проблему, так как это барьер потока, и я хочу, чтобы производитель не блокировал.

@ Замечание sfossin об обмене ссылками на очереди является хорошим; я хотел, чтобы в тот момент, когда потребитель начал извлекать и обрабатывать элементы из очереди, все эти элементы очереди должны быть завершены, и производитель не может добавлять какие-либо элементы впоследствии; производитель теперь должен добавить элементы в другую очередь. Таким образом, парный / замененный набор атомарных ссылок не будет работать.

(Это похоже на то, что если есть 2 школьных автобуса, один из которых всегда ждет пассажиров, а другой всегда доставляет их в другое место. Как только водитель отъезжает, вот и все, вам нужно сесть на другой автобус. Наличие ссылок позволяет производителям получить доступ к шине, даже если она уже оставлена, что недопустимо.)

Я думаю, что вместо этого я буду использовать один ConcurrentLinkedQueue и иметь значение часового, которое потребитель добавляет в очередь. Это позволяет иметь несколько производителей, а не только 1. Чтобы потребитель мог обрабатывать партии элементов в очереди, он ожидает, что в очереди будет хотя бы 1 элемент, а затем вставляет страж в конце очереди и удаляет элементы, пока не будет удален страж. Затем потребитель делает все, что ему нужно делать между партиями. Это поведение, которое я хотел.

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

Ответы [ 3 ]

2 голосов
/ 11 марта 2009
2 голосов
/ 11 марта 2009

Очередь с блокировкой чтения / записи, вероятно, является лучшей идеей. Поскольку, если в противном случае вам придется копировать в локальную очередь атомарно.

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

RWLock позволит использовать несколько потребителей / производителей.

Есть ли причина, по которой вы хотели бы держаться подальше от RWLocks?

Как и в случае любой блокировки, замок следует удерживать в течение минимально возможного времени, чтобы предотвратить голодание.

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

 class LockedQueue
 {
    private final List<Data>  q = new ArrayList<Data>();
    private final Lock lock = new ReentrantLock();

    public void get( List<Data> consumerQ ) {
        if( lock.tryLock() ) { try { consumerQ .addAll( q ); q.clear(); } finally { lock.unlock(); }}
    }
    public Data put( List<Data> producerQ ) {
        if( lock.tryLock() ) { try { return q.addAll( producerQ  ); producerQ .clear(); } finally { lock.unlock(); }}
    }
    public void clear() {
        lock.lock(); try { q.clear(); } finally { lock.unlock(); }
    }
 }

с потребителем, вызывающим get (), когда он пуст или в конце каждого цикла, и потребителем, вызывающим put, после добавления такого количества элементов или времени или ...

0 голосов
/ 11 марта 2009

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

Проблема, которую вы описываете, очень распространена, хотя я вроде бы и ее ожидал найти. Возможно в Java 1.7.

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