[ACCEPTED]-BlockingQueue - blocked drainTo() methods-concurrency

Accepted answer
Score: 40

Are you referring to the comment in the 23 JavaDoc:

Further, the behavior of this operation 22 is undefined if the specified collection is 21 modified while the operation is in progress.

I 20 believe that this refers to the collection 19 list in your example:

blockingQueue.drainTo(list);

meaning that you cannot 18 modify list at the same time you are draining 17 from blockingQueue into list. However, the blocking queue 16 internally synchronizes so that when drainTo is 15 called, puts and (see note below) gets will block. If 14 it did not do this, then it would not be 13 truly Thread-safe. You can look at the 12 source code and verify that drainTo is Thread-safe 11 regarding the blocking queue itself.

Alternately, do 10 you mean that when you call drainTo that you want 9 it to block until at least one object has 8 been added to the queue? In that case, you 7 have little choice other than:

list.add(blockingQueue.take());
blockingQueue.drainTo(list);

to block until 6 one or more items have been added, and then 5 drain the entire queue into the collection 4 list.

Note: As of Java 7, a separate lock is 3 used for gets and puts. Put operations are 2 now permitted during a drainTo (and a number 1 of other take operations).

Score: 19

If you happen to use Google Guava, there's 4 a nifty Queues.drain() method.

Drains the queue as BlockingQueue.drainTo(Collection, int), but 3 if the requested numElements elements are not available, it 2 will wait for them up to the specified 1 timeout.

Score: 9

I found this pattern useful.

List<byte[]> blobs = new ArrayList<byte[]>();
if (queue.drainTo(blobs, batch) == 0) {
   blobs.add(queue.take());
}

0

Score: 0

With the API available, I don't think you 6 are going to get much more elegant. Other 5 than you can remove the size test.

If you 4 are wanting to atomically retrieve a contiguous 3 sequence of elements even if another removal 2 operation coincides, I don't believe even 1 drainTo guarantees that.

More Related questions