20 |
|
* <p>This is a classic "bounded buffer", in which a |
21 |
|
* fixed-sized array holds elements inserted by producers and |
22 |
|
* extracted by consumers. Once created, the capacity cannot be |
23 |
< |
* increased. Attempts to put an element to a full queue will |
24 |
< |
* result in the put operation blocking; attempts to retrieve an |
23 |
> |
* increased. Attempts to <tt>put</tt> an element into a full queue |
24 |
> |
* will result in the operation blocking; attempts to <tt>take</tt> an |
25 |
|
* element from an empty queue will similarly block. |
26 |
|
* |
27 |
|
* <p> This class supports an optional fairness policy for ordering |
140 |
|
/** |
141 |
|
* Creates an <tt>ArrayBlockingQueue</tt> with the given (fixed) |
142 |
|
* capacity and default access policy. |
143 |
+ |
* |
144 |
|
* @param capacity the capacity of this queue |
145 |
|
* @throws IllegalArgumentException if <tt>capacity</tt> is less than 1 |
146 |
|
*/ |
151 |
|
/** |
152 |
|
* Creates an <tt>ArrayBlockingQueue</tt> with the given (fixed) |
153 |
|
* capacity and the specified access policy. |
154 |
+ |
* |
155 |
|
* @param capacity the capacity of this queue |
156 |
|
* @param fair if <tt>true</tt> then queue accesses for threads blocked |
157 |
< |
* on insertion or removal, are processed in FIFO order; if <tt>false</tt> |
158 |
< |
* the access order is unspecified. |
157 |
> |
* on insertion or removal, are processed in FIFO order; |
158 |
> |
* if <tt>false</tt> the access order is unspecified. |
159 |
|
* @throws IllegalArgumentException if <tt>capacity</tt> is less than 1 |
160 |
|
*/ |
161 |
|
public ArrayBlockingQueue(int capacity, boolean fair) { |
172 |
|
* capacity, the specified access policy and initially containing the |
173 |
|
* elements of the given collection, |
174 |
|
* added in traversal order of the collection's iterator. |
175 |
+ |
* |
176 |
|
* @param capacity the capacity of this queue |
177 |
|
* @param fair if <tt>true</tt> then queue accesses for threads blocked |
178 |
< |
* on insertion or removal, are processed in FIFO order; if <tt>false</tt> |
179 |
< |
* the access order is unspecified. |
178 |
> |
* on insertion or removal, are processed in FIFO order; |
179 |
> |
* if <tt>false</tt> the access order is unspecified. |
180 |
|
* @param c the collection of elements to initially contain |
181 |
|
* @throws IllegalArgumentException if <tt>capacity</tt> is less than |
182 |
< |
* <tt>c.size()</tt>, or less than 1. |
183 |
< |
* @throws NullPointerException if <tt>c</tt> or any element within it |
184 |
< |
* is <tt>null</tt>. |
182 |
> |
* <tt>c.size()</tt>, or less than 1. |
183 |
> |
* @throws NullPointerException if the specified collection or any |
184 |
> |
* of its elements are null |
185 |
|
*/ |
186 |
|
public ArrayBlockingQueue(int capacity, boolean fair, |
187 |
|
Collection<? extends E> c) { |
194 |
|
} |
195 |
|
|
196 |
|
/** |
197 |
< |
* Inserts the specified element at the tail of this queue if possible, |
198 |
< |
* returning immediately if this queue is full. |
197 |
> |
* Inserts the specified element at the tail of this queue if it is |
198 |
> |
* possible to do so immediately without exceeding the queue's capacity, |
199 |
> |
* returning <tt>true</tt> upon success and throwing an |
200 |
> |
* <tt>IllegalStateException</tt> if this queue is full. |
201 |
|
* |
202 |
< |
* @param e the element to add. |
203 |
< |
* @return <tt>true</tt> if it was possible to add the element to |
204 |
< |
* this queue, else <tt>false</tt> |
205 |
< |
* @throws NullPointerException if the specified element is <tt>null</tt>. |
202 |
> |
* @param e the element to add |
203 |
> |
* @return <tt>true</tt> (as per the spec for {@link Collection#add}) |
204 |
> |
* @throws IllegalStateException if this queue is full |
205 |
> |
* @throws NullPointerException if the specified element is null |
206 |
> |
*/ |
207 |
> |
public boolean add(E e) { |
208 |
> |
return super.add(e); |
209 |
> |
} |
210 |
> |
|
211 |
> |
/** |
212 |
> |
* Inserts the specified element at the tail of this queue if it is |
213 |
> |
* possible to do so immediately without exceeding the queue's capacity, |
214 |
> |
* returning <tt>true</tt> upon success and <tt>false</tt> if this queue |
215 |
> |
* is full. This method is generally preferable to method {@link #add}, |
216 |
> |
* which can fail to insert an element only by throwing an exception. |
217 |
> |
* |
218 |
> |
* @throws NullPointerException if the specified element is null |
219 |
|
*/ |
220 |
|
public boolean offer(E e) { |
221 |
|
if (e == null) throw new NullPointerException(); |
234 |
|
} |
235 |
|
|
236 |
|
/** |
237 |
< |
* Inserts the specified element at the tail of this queue, waiting if |
238 |
< |
* necessary up to the specified wait time for space to become available. |
239 |
< |
* @param e the element to add |
240 |
< |
* @param timeout how long to wait before giving up, in units of |
241 |
< |
* <tt>unit</tt> |
242 |
< |
* @param unit a <tt>TimeUnit</tt> determining how to interpret the |
243 |
< |
* <tt>timeout</tt> parameter |
244 |
< |
* @return <tt>true</tt> if successful, or <tt>false</tt> if |
245 |
< |
* the specified waiting time elapses before space is available. |
246 |
< |
* @throws InterruptedException if interrupted while waiting. |
247 |
< |
* @throws NullPointerException if the specified element is <tt>null</tt>. |
237 |
> |
* Inserts the specified element at the tail of this queue, waiting |
238 |
> |
* for space to become available if the queue is full. |
239 |
> |
* |
240 |
> |
* @throws InterruptedException {@inheritDoc} |
241 |
> |
* @throws NullPointerException {@inheritDoc} |
242 |
> |
*/ |
243 |
> |
public void put(E e) throws InterruptedException { |
244 |
> |
if (e == null) throw new NullPointerException(); |
245 |
> |
final E[] items = this.items; |
246 |
> |
final ReentrantLock lock = this.lock; |
247 |
> |
lock.lockInterruptibly(); |
248 |
> |
try { |
249 |
> |
try { |
250 |
> |
while (count == items.length) |
251 |
> |
notFull.await(); |
252 |
> |
} catch (InterruptedException ie) { |
253 |
> |
notFull.signal(); // propagate to non-interrupted thread |
254 |
> |
throw ie; |
255 |
> |
} |
256 |
> |
insert(e); |
257 |
> |
} finally { |
258 |
> |
lock.unlock(); |
259 |
> |
} |
260 |
> |
} |
261 |
> |
|
262 |
> |
/** |
263 |
> |
* Inserts the specified element at the tail of this queue, waiting |
264 |
> |
* up to the specified wait time for space to become available if |
265 |
> |
* the queue is full. |
266 |
> |
* |
267 |
> |
* @throws InterruptedException {@inheritDoc} |
268 |
> |
* @throws NullPointerException {@inheritDoc} |
269 |
|
*/ |
270 |
|
public boolean offer(E e, long timeout, TimeUnit unit) |
271 |
|
throws InterruptedException { |
294 |
|
} |
295 |
|
} |
296 |
|
|
258 |
– |
|
297 |
|
public E poll() { |
298 |
|
final ReentrantLock lock = this.lock; |
299 |
|
lock.lock(); |
307 |
|
} |
308 |
|
} |
309 |
|
|
310 |
+ |
public E take() throws InterruptedException { |
311 |
+ |
final ReentrantLock lock = this.lock; |
312 |
+ |
lock.lockInterruptibly(); |
313 |
+ |
try { |
314 |
+ |
try { |
315 |
+ |
while (count == 0) |
316 |
+ |
notEmpty.await(); |
317 |
+ |
} catch (InterruptedException ie) { |
318 |
+ |
notEmpty.signal(); // propagate to non-interrupted thread |
319 |
+ |
throw ie; |
320 |
+ |
} |
321 |
+ |
E x = extract(); |
322 |
+ |
return x; |
323 |
+ |
} finally { |
324 |
+ |
lock.unlock(); |
325 |
+ |
} |
326 |
+ |
} |
327 |
+ |
|
328 |
|
public E poll(long timeout, TimeUnit unit) throws InterruptedException { |
329 |
|
final ReentrantLock lock = this.lock; |
330 |
|
lock.lockInterruptibly(); |
350 |
|
} |
351 |
|
} |
352 |
|
|
297 |
– |
/** |
298 |
– |
* Removes a single instance of the specified element from this |
299 |
– |
* queue, if it is present. |
300 |
– |
*/ |
301 |
– |
public boolean remove(Object o) { |
302 |
– |
if (o == null) return false; |
303 |
– |
final E[] items = this.items; |
304 |
– |
final ReentrantLock lock = this.lock; |
305 |
– |
lock.lock(); |
306 |
– |
try { |
307 |
– |
int i = takeIndex; |
308 |
– |
int k = 0; |
309 |
– |
for (;;) { |
310 |
– |
if (k++ >= count) |
311 |
– |
return false; |
312 |
– |
if (o.equals(items[i])) { |
313 |
– |
removeAt(i); |
314 |
– |
return true; |
315 |
– |
} |
316 |
– |
i = inc(i); |
317 |
– |
} |
318 |
– |
|
319 |
– |
} finally { |
320 |
– |
lock.unlock(); |
321 |
– |
} |
322 |
– |
} |
323 |
– |
|
353 |
|
public E peek() { |
354 |
|
final ReentrantLock lock = this.lock; |
355 |
|
lock.lock(); |
360 |
|
} |
361 |
|
} |
362 |
|
|
334 |
– |
public E take() throws InterruptedException { |
335 |
– |
final ReentrantLock lock = this.lock; |
336 |
– |
lock.lockInterruptibly(); |
337 |
– |
try { |
338 |
– |
try { |
339 |
– |
while (count == 0) |
340 |
– |
notEmpty.await(); |
341 |
– |
} catch (InterruptedException ie) { |
342 |
– |
notEmpty.signal(); // propagate to non-interrupted thread |
343 |
– |
throw ie; |
344 |
– |
} |
345 |
– |
E x = extract(); |
346 |
– |
return x; |
347 |
– |
} finally { |
348 |
– |
lock.unlock(); |
349 |
– |
} |
350 |
– |
} |
351 |
– |
|
352 |
– |
/** |
353 |
– |
* Adds the specified element to the tail of this queue, waiting if |
354 |
– |
* necessary for space to become available. |
355 |
– |
* @param e the element to add |
356 |
– |
* @throws InterruptedException if interrupted while waiting. |
357 |
– |
* @throws NullPointerException if the specified element is <tt>null</tt>. |
358 |
– |
*/ |
359 |
– |
public void put(E e) throws InterruptedException { |
360 |
– |
if (e == null) throw new NullPointerException(); |
361 |
– |
final E[] items = this.items; |
362 |
– |
final ReentrantLock lock = this.lock; |
363 |
– |
lock.lockInterruptibly(); |
364 |
– |
try { |
365 |
– |
try { |
366 |
– |
while (count == items.length) |
367 |
– |
notFull.await(); |
368 |
– |
} catch (InterruptedException ie) { |
369 |
– |
notFull.signal(); // propagate to non-interrupted thread |
370 |
– |
throw ie; |
371 |
– |
} |
372 |
– |
insert(e); |
373 |
– |
} finally { |
374 |
– |
lock.unlock(); |
375 |
– |
} |
376 |
– |
} |
377 |
– |
|
363 |
|
// this doc comment is overridden to remove the reference to collections |
364 |
|
// greater in size than Integer.MAX_VALUE |
365 |
|
/** |
366 |
|
* Returns the number of elements in this queue. |
367 |
|
* |
368 |
< |
* @return the number of elements in this queue. |
368 |
> |
* @return the number of elements in this queue |
369 |
|
*/ |
370 |
|
public int size() { |
371 |
|
final ReentrantLock lock = this.lock; |
388 |
|
* <p>Note that you <em>cannot</em> always tell if an attempt to insert |
389 |
|
* an element will succeed by inspecting <tt>remainingCapacity</tt> |
390 |
|
* because it may be the case that another thread is about to |
391 |
< |
* <tt>put</tt> or <tt>take</tt> an element. |
391 |
> |
* insert or remove an element. |
392 |
|
*/ |
393 |
|
public int remainingCapacity() { |
394 |
|
final ReentrantLock lock = this.lock; |
400 |
|
} |
401 |
|
} |
402 |
|
|
403 |
+ |
/** |
404 |
+ |
* Removes a single instance of the specified element from this queue, |
405 |
+ |
* if it is present. More formally, removes an element <tt>e</tt> such |
406 |
+ |
* that <tt>o.equals(e)</tt>, if this queue contains one or more such |
407 |
+ |
* elements. |
408 |
+ |
* Returns <tt>true</tt> if this queue contained the specified element |
409 |
+ |
* (or equivalently, if this queue changed as a result of the call). |
410 |
+ |
* |
411 |
+ |
* @param o element to be removed from this queue, if present |
412 |
+ |
* @return <tt>true</tt> if this queue changed as a result of the call |
413 |
+ |
*/ |
414 |
+ |
public boolean remove(Object o) { |
415 |
+ |
if (o == null) return false; |
416 |
+ |
final E[] items = this.items; |
417 |
+ |
final ReentrantLock lock = this.lock; |
418 |
+ |
lock.lock(); |
419 |
+ |
try { |
420 |
+ |
int i = takeIndex; |
421 |
+ |
int k = 0; |
422 |
+ |
for (;;) { |
423 |
+ |
if (k++ >= count) |
424 |
+ |
return false; |
425 |
+ |
if (o.equals(items[i])) { |
426 |
+ |
removeAt(i); |
427 |
+ |
return true; |
428 |
+ |
} |
429 |
+ |
i = inc(i); |
430 |
+ |
} |
431 |
+ |
|
432 |
+ |
} finally { |
433 |
+ |
lock.unlock(); |
434 |
+ |
} |
435 |
+ |
} |
436 |
|
|
437 |
+ |
/** |
438 |
+ |
* Returns <tt>true</tt> if this queue contains the specified element. |
439 |
+ |
* More formally, returns <tt>true</tt> if and only if this queue contains |
440 |
+ |
* at least one element <tt>e</tt> such that <tt>o.equals(e)</tt>. |
441 |
+ |
* |
442 |
+ |
* @param o object to be checked for containment in this queue |
443 |
+ |
* @return <tt>true</tt> if this queue contains the specified element |
444 |
+ |
*/ |
445 |
|
public boolean contains(Object o) { |
446 |
|
if (o == null) return false; |
447 |
|
final E[] items = this.items; |
461 |
|
} |
462 |
|
} |
463 |
|
|
464 |
+ |
/** |
465 |
+ |
* Returns an array containing all of the elements in this queue, in |
466 |
+ |
* proper sequence. |
467 |
+ |
* |
468 |
+ |
* <p>The returned array will be "safe" in that no references to it are |
469 |
+ |
* maintained by this queue. (In other words, this method must allocate |
470 |
+ |
* a new array). The caller is thus free to modify the returned array. |
471 |
+ |
* |
472 |
+ |
* <p>This method acts as bridge between array-based and collection-based |
473 |
+ |
* APIs. |
474 |
+ |
* |
475 |
+ |
* @return an array containing all of the elements in this queue |
476 |
+ |
*/ |
477 |
|
public Object[] toArray() { |
478 |
|
final E[] items = this.items; |
479 |
|
final ReentrantLock lock = this.lock; |
492 |
|
} |
493 |
|
} |
494 |
|
|
495 |
+ |
/** |
496 |
+ |
* Returns an array containing all of the elements in this queue, in |
497 |
+ |
* proper sequence; the runtime type of the returned array is that of |
498 |
+ |
* the specified array. If the queue fits in the specified array, it |
499 |
+ |
* is returned therein. Otherwise, a new array is allocated with the |
500 |
+ |
* runtime type of the specified array and the size of this queue. |
501 |
+ |
* |
502 |
+ |
* <p>If this queue fits in the specified array with room to spare |
503 |
+ |
* (i.e., the array has more elements than this queue), the element in |
504 |
+ |
* the array immediately following the end of the queue is set to |
505 |
+ |
* <tt>null</tt>. |
506 |
+ |
* |
507 |
+ |
* <p>Like the {@link #toArray()} method, this method acts as bridge between |
508 |
+ |
* array-based and collection-based APIs. Further, this method allows |
509 |
+ |
* precise control over the runtime type of the output array, and may, |
510 |
+ |
* under certain circumstances, be used to save allocation costs. |
511 |
+ |
* |
512 |
+ |
* <p>Suppose <tt>x</tt> is a queue known to contain only strings. |
513 |
+ |
* The following code can be used to dump the queue into a newly |
514 |
+ |
* allocated array of <tt>String</tt>: |
515 |
+ |
* |
516 |
+ |
* <pre> |
517 |
+ |
* String[] y = x.toArray(new String[0]);</pre> |
518 |
+ |
* |
519 |
+ |
* Note that <tt>toArray(new Object[0])</tt> is identical in function to |
520 |
+ |
* <tt>toArray()</tt>. |
521 |
+ |
* |
522 |
+ |
* @param a the array into which the elements of the queue are to |
523 |
+ |
* be stored, if it is big enough; otherwise, a new array of the |
524 |
+ |
* same runtime type is allocated for this purpose |
525 |
+ |
* @return an array containing all of the elements in this queue |
526 |
+ |
* @throws ArrayStoreException if the runtime type of the specified array |
527 |
+ |
* is not a supertype of the runtime type of every element in |
528 |
+ |
* this queue |
529 |
+ |
* @throws NullPointerException if the specified array is null |
530 |
+ |
*/ |
531 |
|
public <T> T[] toArray(T[] a) { |
532 |
|
final E[] items = this.items; |
533 |
|
final ReentrantLock lock = this.lock; |
563 |
|
} |
564 |
|
} |
565 |
|
|
491 |
– |
|
566 |
|
/** |
567 |
|
* Atomically removes all of the elements from this queue. |
568 |
|
* The queue will be empty after this call returns. |
587 |
|
} |
588 |
|
} |
589 |
|
|
590 |
+ |
/** |
591 |
+ |
* @throws UnsupportedOperationException {@inheritDoc} |
592 |
+ |
* @throws ClassCastException {@inheritDoc} |
593 |
+ |
* @throws NullPointerException {@inheritDoc} |
594 |
+ |
* @throws IllegalArgumentException {@inheritDoc} |
595 |
+ |
*/ |
596 |
|
public int drainTo(Collection<? super E> c) { |
597 |
|
if (c == null) |
598 |
|
throw new NullPointerException(); |
623 |
|
} |
624 |
|
} |
625 |
|
|
626 |
< |
|
626 |
> |
/** |
627 |
> |
* @throws UnsupportedOperationException {@inheritDoc} |
628 |
> |
* @throws ClassCastException {@inheritDoc} |
629 |
> |
* @throws NullPointerException {@inheritDoc} |
630 |
> |
* @throws IllegalArgumentException {@inheritDoc} |
631 |
> |
*/ |
632 |
|
public int drainTo(Collection<? super E> c, int maxElements) { |
633 |
|
if (c == null) |
634 |
|
throw new NullPointerException(); |
670 |
|
* construction of the iterator, and may (but is not guaranteed to) |
671 |
|
* reflect any modifications subsequent to construction. |
672 |
|
* |
673 |
< |
* @return an iterator over the elements in this queue in proper sequence. |
673 |
> |
* @return an iterator over the elements in this queue in proper sequence |
674 |
|
*/ |
675 |
|
public Iterator<E> iterator() { |
676 |
|
final ReentrantLock lock = this.lock; |