I find myself repeating this pattern and have often wondered if it is idiomatic in Java or there is a better way of achieving this behaviour.
Problem: Given a producer/consumer setup, the consumer wants to process batches of items, so it uses drainTo(), however drainTo() will poll for existing items and possibly fail to get any items, to avoid this I prefix the drain with a take() to ensure it blocks until at least one item is available.
One problem I get, with a particular dataset, is with many use cases that the batch size is often irregular alternating between (1, N, 1, N). In general is this a common way to solve this problem:
Example:
ArrayBlockingQueue<Foo> queue; function void produce() { while(true) { queue.put(createFoo()); } } function void consumeBatchSpin() { while(true) { List<Foo> batch = Lists.newLinkedList(); queue.drainTo(batch); doSomething(batch); //the problem here is that if nothing is being produced, this loop will spin } } function void consumeBatchTake() { while(true) { List<Foo> batch = Lists.newLinkedList(); batch.add(queue.take()); //force at least one item to be there queue.drainTo(batch); doSomething(batch); } }