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 }