Drains the queue as BlockingQueue#drainTo(Collection, int), but if the requested numElements elements are not available, it will wait for them up to the specified timeout. @param q the blocking queue to be drained @param buffer where to add the transferred elements @param numElement
(
BlockingQueue<E> q,
Collection<? super E> buffer,
int numElements,
long timeout,
TimeUnit unit)
| 291 | */ |
| 292 | |
| 293 | @Beta |
| 294 | @CanIgnoreReturnValue |
| 295 | public static <E> int drain( |
| 296 | BlockingQueue<E> q, |
| 297 | Collection<? super E> buffer, |
| 298 | int numElements, |
| 299 | long timeout, |
| 300 | TimeUnit unit) |
| 301 | throws InterruptedException { |
| 302 | Preconditions.checkNotNull(buffer); |
| 303 | /* |
| 304 | * This code performs one System.nanoTime() more than necessary, and in return, the time to |
| 305 | * execute Queue#drainTo is not added *on top* of waiting for the timeout (which could make |
| 306 | * the timeout arbitrarily inaccurate, given a queue that is slow to drain). |
| 307 | */ |
| 308 | long deadline = System.nanoTime() + unit.toNanos(timeout); |
| 309 | int added = 0; |
| 310 | while (added < numElements) { |
| 311 | // we could rely solely on #poll, but #drainTo might be more efficient when there are multiple |
| 312 | // elements already available (e.g. LinkedBlockingQueue#drainTo locks only once) |
| 313 | added += q.drainTo(buffer, numElements - added); |
| 314 | if (added < numElements) { // not enough elements immediately available; will have to poll |
| 315 | E e = q.poll(deadline - System.nanoTime(), TimeUnit.NANOSECONDS); |
| 316 | if (e == null) { |
| 317 | break; // we already waited enough, and there are no more elements in sight |
| 318 | } |
| 319 | buffer.add(e); |
| 320 | added++; |
| 321 | } |
| 322 | } |
| 323 | return added; |
| 324 | } |
| 325 | |
| 326 | /** |
| 327 | * Drains the queue as {@linkplain #drain(BlockingQueue, Collection, int, long, TimeUnit)}, |
nothing calls this directly
no test coverage detected