[concurrency-interest] Use of blocked queues

Calum MacLean cnmaclean at hotmail.com
Mon May 30 09:22:24 EDT 2005


You're correct - I was planning using a LinkedBlockingQueue, so offer() 
wouldn't work.

I'll step back to explain my purpose.
My application is getting "messages" sent from a socket.  What I want to do 
is provide a generic interface for receiving these messages, which allow 
clients to choose whether to read them (and therefore block if there are 
none available) or to poll them (i.e. non-blocking).
For the clients which are using polling, I additionally want to provide a 
notification mechanism for when events arrive in and have not (immediately) 
been read by a waiting reader.
So it looks something like this (simplifying a little):
    interface MessageSource
    {
        Message read();
        Message poll();
        addMessageAvailableListener(MessageAvailableListener listener);
        removeMessageAvailableListener(MessageAvailableListener listener);
    }

I'd also say that the listener is intended to indicate that a new message 
has come in, which hasn't been read immediately, but there's no guarantee 
intended of whether it will still be there when you poll.  So the race 
condition you mentioned is OK.  Also, in most situations there would be a 
single client, choosing to use either reading or polling; so typically the 
occurrence of the race condition would be avoided because the client would 
just be using a single mechanism for reading.

I can achieve this relatively easily directly, by using a common object for 
synchronising around, and keeping a note of the number of readers.  But I 
thought that part of the raison-d'etre of java.util.concurrency was so that 
most uses of concurrency could use the higher level constructs (queues 
etc.), and not have to worry about using locks etc. directly.  So I was 
wondering if I was missing something in how I could achieve what I wanted to 
do.

I'd also note that, if I synchronise around e.g. a LinkedList, then I can 
synchronise around it for things other than putting/taking.  But I can't get 
a handle on the internal locks within (e.g.) LinedBlockingQueue to do 
something similar there.

Thanks for your help,
Calum


>I wrote:
>>
>> Given this, from what I understand of your intent,
>> I think you can do something like:
>>    if (!q.offer(data)) {
>>      fireEvent();
>>      q.put(data);
>>    }
>>
>
> I should have noted that this snippet is only reliable for
> SynchronousQueues, which may or may not be best for you here.
> If you use a queue with storage (LinkedBlockingQueue etc),
> you probably want to always fire an event, because offer() cannot
> distinguish queuing from taking by another thread.
> While you might be able to heuristically cut down on the number of
> events by first putting the item, and then checking of the queue
> is still empty, this won't do a lot of good because even if
> there is a waiting taker, it usually will not have completely taken the
> item by the time you check.
>
> -Doug
>
> 


More information about the Concurrency-interest mailing list