danny.lesnik
danny.lesnik

Reputation: 18639

BlockingQueue - Fetch only specific object.

I have the following blockingQueue;

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

where

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

I have a producers which put messages to queue.

now my goal is to create consumers which will be able to fetch from queue only messages for specific with specific author? Is it possible?

If not what could be alternative to BlockingQueue?

Upvotes: 1

Views: 2606

Answers (3)

Mark Peters
Mark Peters

Reputation: 81054

It's certainly possible, assuming you are flexible about what happens to the elements that get to the front of the queue that don't match your criteria.

One simple way would be something like

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

Now if you were wondering if you could cherry-pick elements from the queue, leaving the other elements in place, then no that is not possible with the queue datatype. You could make it work with some kind of Deque (double-ended queue), where you put the elements you don't care about in a temporary stack and then reinsert them back in when you find one you want. But you're definitely best to just use a separate queue that only contains the elements you care about.

For instance, you could have a thread that consumes every message in the queue and then redispatches it to a more specific queue:

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

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

Then set up your consumer to consume the correct author queue.

Upvotes: 3

John Vint
John Vint

Reputation: 40256

You can use a ConcurrentMap<String,BlockingQueue<Message>> where the string is the 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);
}

This will require a unique BlockingQueue for each author.

Upvotes: 4

Jakub Zaverka
Jakub Zaverka

Reputation: 8874

You could try PriorityBlockingQueue or keep separate Queues for every message type, but then you would have to sychronize by some higher object (otherwise multiple threads could fetch multiple messages at the same time).

Upvotes: 0

Related Questions