001    /*
002     * Copyright 1999-2004 The Apache Software Foundation.
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     * 
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.apache.commons.threadpool;
017    
018    import java.util.LinkedList;
019    
020    import org.apache.commons.logging.Log;
021    import org.apache.commons.logging.LogFactory;
022    
023    /** 
024     * A multithreaded blocking queue which is very useful for 
025     * implementing producer-consumer style threading patterns.
026     * <p>
027     * Multiple blocking threads can wait for items being added
028     * to the queue while other threads add to the queue.
029     * <p>
030     * Non blocking and timout based modes of access are possible as well.
031     *
032     * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
033     * @version $Revision: 155472 $
034     */
035    public class MTQueue {
036    
037        /** The Log to which logging calls will be made. */
038        private Log log = LogFactory.getLog(MTQueue.class);
039    
040    
041        private LinkedList list = new LinkedList();
042        private long defaultTimeout = 10000;
043    
044        public MTQueue() {
045        }
046    
047        /**
048         * Returns the current number of object in the queue
049         */
050        public synchronized int size() {
051            return list.size();
052        }
053    
054        /** 
055         * adds a new object to the end of the queue.
056         * At least one thread will be notified.
057         */
058        public synchronized void add(Object object) {
059            list.add( object );
060            notify();
061        }
062    
063        /** 
064         * Removes the first object from the queue, blocking until one is available.
065         * Note that this method will never return null and could block forever.
066         */
067        public synchronized Object remove() {
068            while (true) {
069                Object answer = removeNoWait();
070                if ( answer != null ) {
071                    return answer;
072                }
073                try {
074                    wait( defaultTimeout );
075                }
076                catch (InterruptedException e) {
077                    log.error( "Thread was interrupted: " + e, e );
078                }
079            }
080        }
081    
082        /** 
083         * Removes the first object from the queue, blocking only up to the given
084         * timeout time.
085         */
086        public synchronized Object remove(long timeout) {
087            Object answer = removeNoWait();
088            if (answer == null) {
089                try {
090                    wait( timeout );
091                }
092                catch (InterruptedException e) {
093                    log.error( "Thread was interrupted: " + e, e );
094                }
095                answer = removeNoWait();
096            }
097            return answer;
098        }
099    
100        /** 
101         * Removes the first object from the queue without blocking.
102         * This method will return immediately with an item from the queue or null.
103         * 
104         * @return the first object removed from the queue or null if the
105         * queue is empty
106         */
107        public synchronized Object removeNoWait() {
108            if ( ! list.isEmpty() ) {
109                return list.removeFirst();
110            }
111            return null;
112        }
113    
114    }