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. */publicclass BlockingQueue implements Cloneable{ /** * The underlying Vector this BlockingQueue is using. */privatefinal Vector queue; /** * The lock we use to synchronize pushing. */privatefinal Object pushLock = new String("BlockingQueue pushLock"); /** * The lock we use to synchronize popping. */privatefinal Object popLock = new String("BlockingQueue popLock"); /** * Creates a new, empty BlockingQueue. */public BlockingQueue(){ queue = new Vector(); } /** * Pushes an element into the queue. */publicvoid 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()) thrownew 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()) thrownew 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). */publicboolean isEmpty(){ return queue.isEmpty(); } /** * Returns true if the given element is in the queue. */publicboolean contains(Object element){ return queue.contains(element); } /** * Returns the size of the queue. */publicint 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. */publicvoid removeAllElements(){ queue.removeAllElements(); } /** * Removes all elements from this queue. */publicvoid clear(){ queue.removeAllElements(); } /** * Returns a shallow copy of this BlockingQueue. */publicsynchronized Object clone(){ BlockingQueue copy = new BlockingQueue(); Enumeration elems = getElements(); while (elems.hasMoreElements()){ Object item = elems.nextElement(); copy.push(item); } return copy; } }
Related examples in the same category