20 |
|
* in the offer operation blocking; attempts to retrieve an element from |
21 |
|
* an empty queue will similarly block. Threads blocked on an insertion or |
22 |
|
* removal will be services in FIFO order. |
23 |
< |
**/ |
23 |
> |
* @since 1.5 |
24 |
> |
* @author Doug Lea |
25 |
> |
*/ |
26 |
|
public class ArrayBlockingQueue<E> extends AbstractQueue<E> |
27 |
|
implements BlockingQueue<E>, java.io.Serializable { |
28 |
|
|
29 |
+ |
/** The queued items */ |
30 |
|
private transient final E[] items; |
31 |
< |
private transient int takeIndex; |
31 |
> |
/** items index for next take, poll or remove */ |
32 |
> |
private transient int takeIndex; |
33 |
> |
/** items index for next put, offer, or add. */ |
34 |
|
private transient int putIndex; |
35 |
+ |
/** Number of items in the queue */ |
36 |
|
private int count; |
37 |
|
|
38 |
|
/** |
47 |
|
* found in any textbook. |
48 |
|
*/ |
49 |
|
|
50 |
+ |
/** Main lock gurding all access */ |
51 |
|
private final FairReentrantLock lock = new FairReentrantLock(); |
52 |
+ |
/** Condition wor waiting takes */ |
53 |
|
private final Condition notEmpty = lock.newCondition(); |
54 |
+ |
/** Condition for wiating puts */ |
55 |
|
private final Condition notFull = lock.newCondition(); |
56 |
|
|
57 |
|
// Internal helper methods |
176 |
|
|
177 |
|
/** Insert a new element into the queue, blocking if the queue is full. */ |
178 |
|
public void put(E x) throws InterruptedException { |
179 |
< |
if (x == null) throw new IllegalArgumentException(); |
179 |
> |
if (x == null) throw new NullPointerException(); |
180 |
|
lock.lockInterruptibly(); |
181 |
|
try { |
182 |
|
try { |
196 |
|
} |
197 |
|
|
198 |
|
/** Remove and return the first element from the queue, blocking |
199 |
< |
* is the queue is empty. */ |
199 |
> |
* if the queue is empty. |
200 |
> |
*/ |
201 |
|
public E take() throws InterruptedException { |
202 |
|
lock.lockInterruptibly(); |
203 |
|
try { |
220 |
|
|
221 |
|
/** Attempt to insert a new element into the queue, but return |
222 |
|
* immediately without inserting the element if the queue is full. |
223 |
< |
* @return <tt>true</tt> if the element was inserted successfully, <tt>false</tt> otherwise |
223 |
> |
* @return <tt>true</tt> if the element was inserted successfully, |
224 |
> |
* <tt>false</tt> otherwise |
225 |
|
*/ |
226 |
|
public boolean offer(E x) { |
227 |
< |
if (x == null) throw new IllegalArgumentException(); |
227 |
> |
if (x == null) throw new NullPointerException(); |
228 |
|
lock.lock(); |
229 |
|
try { |
230 |
|
if (count == items.length) |
242 |
|
|
243 |
|
/** Attempt to retrieve the first insert element from the queue, |
244 |
|
* but return immediately if the queue is empty. |
245 |
< |
* @return The first element of the queue if the queue is not empty, or <tt>null</tt> otherwise. |
245 |
> |
* @return The first element of the queue if the queue is not |
246 |
> |
* empty, or <tt>null</tt> otherwise. |
247 |
|
*/ |
248 |
|
public E poll() { |
249 |
|
lock.lock(); |
269 |
|
* parameter |
270 |
|
* @return <tt>true</tt> if the element was inserted successfully, |
271 |
|
* <tt>false</tt> otherwise |
272 |
+ |
* @throws InterruptedException if interrupted while waiting |
273 |
|
*/ |
274 |
|
public boolean offer(E x, long timeout, TimeUnit unit) throws InterruptedException { |
275 |
< |
if (x == null) throw new IllegalArgumentException(); |
275 |
> |
if (x == null) throw new NullPointerException(); |
276 |
|
lock.lockInterruptibly(); |
277 |
|
long nanos = unit.toNanos(timeout); |
278 |
|
try { |
308 |
|
* parameter |
309 |
|
* @return The first element of the queue if an item was |
310 |
|
* successfully retrieved, or <tt>null</tt> otherwise. |
311 |
+ |
* @throws InterruptedException if interrupted while waiting |
312 |
|
* |
313 |
|
*/ |
314 |
|
public E poll(long timeout, TimeUnit unit) throws InterruptedException { |
347 |
|
public E peek() { |
348 |
|
lock.lock(); |
349 |
|
try { |
350 |
< |
return (count == 0)? null : items[takeIndex]; |
350 |
> |
return (count == 0) ? null : items[takeIndex]; |
351 |
|
} |
352 |
|
finally { |
353 |
|
lock.unlock(); |
355 |
|
} |
356 |
|
|
357 |
|
|
344 |
– |
/** |
345 |
– |
* Removes one occurrence in this list of the specified element. |
346 |
– |
* If this list does not contain the element, it is |
347 |
– |
* unchanged. More formally, removes an element |
348 |
– |
* such that <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt> (if |
349 |
– |
* such an element exists). |
350 |
– |
* |
351 |
– |
* @param o element to be removed from this list, if present. |
352 |
– |
* @return <tt>true</tt> if this list contained the specified element. |
353 |
– |
* @throws ClassCastException if the type of the specified element |
354 |
– |
* is incompatible with this list (optional). |
355 |
– |
* @throws NullPointerException if the specified element is null and this |
356 |
– |
* list does not support null elements (optional). |
357 |
– |
* @throws UnsupportedOperationException if the <tt>remove</tt> method is |
358 |
– |
* not supported by this list. |
359 |
– |
*/ |
358 |
|
public boolean remove(Object x) { |
359 |
+ |
if (x == null) return false; |
360 |
|
lock.lock(); |
361 |
|
try { |
362 |
|
int i = takeIndex; |
377 |
|
} |
378 |
|
} |
379 |
|
|
381 |
– |
|
382 |
– |
/** |
383 |
– |
* Returns <tt>true</tt> if this list contains the specified element. |
384 |
– |
* More formally, returns <tt>true</tt> if and only if this list contains |
385 |
– |
* at least one element <tt>e</tt> such that |
386 |
– |
* <tt>(o==null ? e==null : o.equals(e))</tt>. |
387 |
– |
* |
388 |
– |
* @param o element whose presence in this list is to be tested. |
389 |
– |
* @return <tt>true</tt> if this list contains the specified element. |
390 |
– |
* @throws ClassCastException if the type of the specified element |
391 |
– |
* is incompatible with this list (optional). |
392 |
– |
* @throws NullPointerException if the specified element is null and this |
393 |
– |
* list does not support null elements (optional). |
394 |
– |
*/ |
380 |
|
public boolean contains(Object x) { |
381 |
+ |
if (x == null) return false; |
382 |
|
lock.lock(); |
383 |
|
try { |
384 |
|
int i = takeIndex; |
395 |
|
} |
396 |
|
} |
397 |
|
|
412 |
– |
/** |
413 |
– |
* Returns an array containing all of the elements in the queue in proper |
414 |
– |
* sequence. Obeys the general contract of the |
415 |
– |
* <tt>Collection.toArray</tt> method. |
416 |
– |
* |
417 |
– |
* @return an array containing all of the elements in this list in proper |
418 |
– |
* sequence. |
419 |
– |
* @see Arrays#asList(Object[]) |
420 |
– |
*/ |
398 |
|
public Object[] toArray() { |
399 |
|
lock.lock(); |
400 |
|
try { |
412 |
|
} |
413 |
|
} |
414 |
|
|
438 |
– |
/** |
439 |
– |
* Returns an array containing all of the elements in this queue in proper |
440 |
– |
* sequence; the runtime type of the returned array is that of the |
441 |
– |
* specified array. Obeys the general contract of the |
442 |
– |
* <tt>Collection.toArray(Object[])</tt> method. |
443 |
– |
* |
444 |
– |
* @param a the array into which the elements of this list are to |
445 |
– |
* be stored, if it is big enough; otherwise, a new array of the |
446 |
– |
* same runtime type is allocated for this purpose. |
447 |
– |
* @return an array containing the elements of this list. |
448 |
– |
* |
449 |
– |
* @throws ArrayStoreException if the runtime type of the specified array |
450 |
– |
* is not a supertype of the runtime type of every element in |
451 |
– |
* this list. |
452 |
– |
* @throws NullPointerException if the specified array is <tt>null</tt>. |
453 |
– |
*/ |
415 |
|
public <T> T[] toArray(T[] a) { |
416 |
|
lock.lock(); |
417 |
|
try { |
457 |
|
lock.unlock(); |
458 |
|
} |
459 |
|
} |
460 |
< |
|
460 |
> |
|
461 |
> |
/** |
462 |
> |
* Iterator for ArrayBlockingQueue |
463 |
> |
*/ |
464 |
|
private class Itr implements Iterator<E> { |
465 |
|
/** |
466 |
|
* Index of element to be returned by next, |
467 |
|
* or a negative number if no such. |
468 |
|
*/ |
469 |
< |
int nextIndex; |
469 |
> |
private int nextIndex; |
470 |
|
|
471 |
|
/** |
472 |
|
* nextItem holds on to item fields because once we claim |
474 |
|
* the following next() call even if it was in the process of |
475 |
|
* being removed when hasNext() was called. |
476 |
|
**/ |
477 |
< |
E nextItem; |
477 |
> |
private E nextItem; |
478 |
|
|
479 |
|
/** |
480 |
|
* Index of element returned by most recent call to next. |
481 |
|
* Reset to -1 if this element is deleted by a call to remove. |
482 |
|
*/ |
483 |
< |
int lastRet; |
483 |
> |
private int lastRet; |
484 |
|
|
485 |
|
Itr() { |
486 |
|
lastRet = -1; |
556 |
|
* |
557 |
|
* @serialData The maximumSize is emitted (int), followed by all of |
558 |
|
* its elements (each an <tt>E</tt>) in the proper order. |
559 |
+ |
* @param s the stream |
560 |
|
*/ |
561 |
|
private void writeObject(java.io.ObjectOutputStream s) |
562 |
|
throws java.io.IOException { |
578 |
|
/** |
579 |
|
* Reconstitute the Queue instance from a stream (that is, |
580 |
|
* deserialize it). |
581 |
+ |
* @param s the stream |
582 |
|
*/ |
583 |
|
private void readObject(java.io.ObjectInputStream s) |
584 |
|
throws java.io.IOException, ClassNotFoundException { |
600 |
|
/** |
601 |
|
* Throw away the object created with readObject, and replace it |
602 |
|
* with a usable ArrayBlockingQueue. |
603 |
+ |
* @return the ArrayBlockingQueue |
604 |
|
*/ |
605 |
|
private Object readResolve() throws java.io.ObjectStreamException { |
606 |
|
E[] array = deserializedItems; |