BlockingQueue - выборка только определенного объекта. - PullRequest
1 голос
/ 19 марта 2012

У меня есть следующая блокировкаQueue;

  final BlockingQueue<Message> blockingQueue = new LinkedBlockingQueue<Message>();

где

public class Message {
    private String author;
    private String text;
        .......
//setters and getters
.....
}

У меня есть производители, которые помещают сообщения в очередь.

Теперь моя цель - создать потребителей, которые смогут извлекать из очереди только сообщения для конкретного автора? Является ли это возможным?

Если нет, то что может быть альтернативой BlockingQueue?

Ответы [ 3 ]

4 голосов
/ 19 марта 2012

Вы можете использовать ConcurrentMap<String,BlockingQueue<Message>>, где строка является author

ConcurrentMap<String,BlockingQueue<Message>> map = ...;
public Message consume(String str){
  return map.get(str).take();
}
public void produce(Message message){
  map.get(message.getAuthor()).put(message);
}

Для этого потребуется уникальный BlockingQueue для каждого автора.

3 голосов
/ 19 марта 2012

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

Одним простым способом было бы что-то вроде

while (true) {
   Message message = blockingQueue.take();
   if ( !message.author.equals(expectedAuthor) ) {
      continue;
   }
}

Теперь, если вам интересно, можете ли вы cherry-pick элементов из очереди, оставив другие элементы на месте, то нет, это невозможно с типом данных очереди. Вы можете заставить его работать с какой-то Deque (двусторонней очередью), где вы помещаете элементы, которые вам не нужны, во временный стек, а затем снова вставляете их обратно, когда найдете нужный. Но вам определенно лучше использовать отдельную очередь, которая содержит только те элементы, которые вас интересуют.

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

Map<String, BlockingQueue<Message>> authorQueues;
BlockingQueue<Message> allMessages;

while(true) {
    Message nextMessage = allMessages.take();
    authorQueues.get(nextMessage.getAuthor()).put(nextMessage);
}

Затем настройте своего потребителя на использование правильной очереди авторов.

0 голосов
/ 19 марта 2012

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

...