001package horstmann.ch09_queue2; 002import java.util.ArrayList; 003import java.util.concurrent.locks.Condition; 004import java.util.concurrent.locks.Lock; 005import java.util.concurrent.locks.ReentrantLock; 006 007/** 008 A first-in, first-out bounded collection of objects. 009 */ 010public class BoundedQueue<E> 011{ 012 /** 013 Constructs an empty queue. 014 @param capacity the maximum capacity of the queue 015 */ 016 public BoundedQueue(int capacity) 017 { 018 elements = new ArrayList<E>(capacity); 019 head = 0; 020 tail = 0; 021 size = 0; 022 } 023 024 /** 025 Removes the object at the head. 026 @return the object that has been removed from the queue 027 */ 028 public E remove() throws InterruptedException 029 { 030 queueLock.lock(); 031 try 032 { 033 while (size == 0) 034 valueAvailableCondition.await(); 035 E r = elements.get(head); 036 head++; 037 size--; 038 if (head == elements.size()) 039 head = 0; 040 spaceAvailableCondition.signalAll(); 041 return r; 042 } 043 finally 044 { 045 queueLock.unlock(); 046 } 047 } 048 049 /** 050 Appends an object at the tail. 051 @param newValue the object to be appended 052 */ 053 public void add(E newValue) throws InterruptedException 054 { 055 queueLock.lock(); 056 try 057 { 058 while (size == elements.size()) 059 spaceAvailableCondition.await(); 060 elements.set(tail,newValue); 061 tail++; 062 size++; 063 if (tail == elements.size()) 064 tail = 0; 065 valueAvailableCondition.signalAll(); 066 } 067 finally 068 { 069 queueLock.unlock(); 070 } 071 } 072 073 private ArrayList<E> elements; 074 private int head; 075 private int tail; 076 private int size; 077 078 private Lock queueLock = new ReentrantLock(); 079 private Condition spaceAvailableCondition 080 = queueLock.newCondition(); 081 private Condition valueAvailableCondition 082 = queueLock.newCondition(); 083}