01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package horstmann.ch09_queue2;
import java.util.ArrayList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
    A first-in, first-out bounded collection of objects.
 */
public class BoundedQueue<E>
{
  /**
       Constructs an empty queue.
       @param capacity the maximum capacity of the queue
   */
  public BoundedQueue(int capacity)
  {
    elements = new ArrayList<E>(capacity);
    head = 0;
    tail = 0;
    size = 0;
  }

  /**
       Removes the object at the head.
       @return the object that has been removed from the queue
   */
  public E remove() throws InterruptedException
  {
    queueLock.lock();
    try
    {
      while (size == 0)
        valueAvailableCondition.await();
      E r = elements.get(head);
      head++;
      size--;
      if (head == elements.size())
        head = 0;
      spaceAvailableCondition.signalAll();
      return r;
    }
    finally
    {
      queueLock.unlock();
    }
  }

  /**
       Appends an object at the tail.
       @param newValue the object to be appended
   */
  public void add(E newValue) throws InterruptedException
  {
    queueLock.lock();
    try
    {
      while (size == elements.size())
        spaceAvailableCondition.await();
      elements.set(tail,newValue);
      tail++;
      size++;
      if (tail == elements.size())
        tail = 0;
      valueAvailableCondition.signalAll();
    }
    finally
    {
      queueLock.unlock();
    }
  }

  private ArrayList<E> elements;
  private int head;
  private int tail;
  private int size;

  private Lock queueLock = new ReentrantLock();
  private Condition spaceAvailableCondition
  = queueLock.newCondition();
  private Condition valueAvailableCondition
  = queueLock.newCondition();
}