Mega Code Archive

 
Categories / Java / Collections Data Structure
 

Blocking Queue

/**  * The utillib library.  * More information is available at http://www.jinchess.com/.  * Copyright (C) 2002 Alexander Maryanovsky.  * All rights reserved.  *  * The utillib library is free software; you can redistribute  * it and/or modify it under the terms of the GNU Lesser General Public License  * as published by the Free Software Foundation; either version 2 of the  * License, or (at your option) any later version.  *  * The utillib library is distributed in the hope that it will  * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser  * General Public License for more details.  *  * You should have received a copy of the GNU Lesser General Public License  * along with utillib library; if not, write to the Free Software  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  */ import java.util.Enumeration; import java.util.Vector; /**  * <P>A blocking queue, one that always "contains" elements.  * If it is in fact empty, the pop() and peek() method will block until an  * item is pushed.  * <P><B>NOTE:</B> This class is thread safe.  *  * @author Alexander Maryanovsky.  */ public class BlockingQueue implements Cloneable{   /**    * The underlying Vector this BlockingQueue is using.    */   private final Vector queue;   /**    * The lock we use to synchronize pushing.    */   private final Object pushLock = new String("BlockingQueue pushLock");   /**    * The lock we use to synchronize popping.    */   private final Object popLock = new String("BlockingQueue popLock");   /**    * Creates a new, empty BlockingQueue.    */   public BlockingQueue(){     queue = new Vector();   }   /**    * Pushes an element into the queue.    */   public void push(Object object){     synchronized(pushLock){       queue.addElement(object);       synchronized(this){         notify();       }     }   }   /**    * Pops an element from the queue. If the queue is empty, this method blocks    * until another thread pushes an element into the queue.    *    * @throws InterruptedException if the invoking thread was interrupted    * while waiting for an element to be pushed into the queue.    */   public Object pop() throws InterruptedException{     return pop(0);   }   /**    * Pops an element from the queue. Unlike the pop() method, this method does not block    * for longer than the given amount of milliseconds. When the given amount of milliseconds    * have passed, this method will throw an InterruptedException.    */   public Object pop(long timeout) throws InterruptedException{     synchronized(popLock){       synchronized(this){         if (queue.isEmpty()){           wait(timeout);           if (queue.isEmpty())             throw new InterruptedException("Timed out");         }       }       Object val = queue.firstElement();       queue.removeElementAt(0);       return val;     }   }   /**    * Returns the element on top of the queue without popping it. If the queue    * is empty, this method blocks until another thread pushes an element into    * the queue.    *    * @throws InterruptedException if the invoking thread was interrupted while    * waiting for an element to be pushed into the queue.    */   public Object peek() throws InterruptedException{     return peek(0);   }   /**    * Returns the element on top of the queue without popping it.    * Unlike the peek() method, this method does not block    * for longer than the given amount of milliseconds. When the given amount of milliseconds    * have passed, this method will throw an InterruptedException.    */   public Object peek(long timeout) throws InterruptedException{     synchronized(popLock){       synchronized(this){         if (queue.isEmpty()){           wait(timeout);           if (queue.isEmpty())             throw new InterruptedException("Timed out");         }       }       return queue.firstElement();     }   }   /**    * Returns true if the queue is empty (this returns the actual state of the    * queue, meaning it may return true even though ideologically, a BlockingQueue    * is never empty).    */   public boolean isEmpty(){     return queue.isEmpty();   }   /**    * Returns true if the given element is in the queue.    */   public boolean contains(Object element){     return queue.contains(element);   }   /**    * Returns the size of the queue.    */   public int size(){     return queue.size();   }   /**    * Returns an Enumeration of the elements in this queue. The order of the    * elements is the same as if they were popped from the queue one by one (the    * first element is the first element that would have been popped). <br>    * <B>IMPORTANT:</B> Modifying the queue breaks the returned Enumeration.    */   public Enumeration getElements(){     return queue.elements();   }   /**    * Removes all elements from this queue.    */   public void removeAllElements(){     queue.removeAllElements();   }   /**    * Removes all elements from this queue.    */   public void clear(){     queue.removeAllElements();   }   /**    * Returns a shallow copy of this BlockingQueue.    */   public synchronized Object clone(){     BlockingQueue copy = new BlockingQueue();     Enumeration elems = getElements();     while (elems.hasMoreElements()){       Object item = elems.nextElement();       copy.push(item);     }     return copy;   } }