You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by fe...@apache.org on 2007/03/27 17:10:40 UTC

svn commit: r522946 [2/2] - in /cocoon/trunk/core/cocoon-thread: cocoon-thread-api/src/changes/ cocoon-thread-api/src/main/java/org/apache/cocoon/components/thread/ cocoon-thread-impl/ cocoon-thread-impl/src/changes/ cocoon-thread-impl/src/main/java/or...

Modified: cocoon/trunk/core/cocoon-thread/cocoon-thread-impl/src/main/java/org/apache/cocoon/components/thread/DefaultThreadPool.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-thread/cocoon-thread-impl/src/main/java/org/apache/cocoon/components/thread/DefaultThreadPool.java?view=diff&rev=522946&r1=522945&r2=522946
==============================================================================
--- cocoon/trunk/core/cocoon-thread/cocoon-thread-impl/src/main/java/org/apache/cocoon/components/thread/DefaultThreadPool.java (original)
+++ cocoon/trunk/core/cocoon-thread/cocoon-thread-impl/src/main/java/org/apache/cocoon/components/thread/DefaultThreadPool.java Tue Mar 27 08:10:39 2007
@@ -18,289 +18,604 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.InitializingBean;
 
 import EDU.oswego.cs.dl.util.concurrent.PooledExecutor;
 
-
 /**
  * The DefaultThreadPool class implements the {@link ThreadPool} interface.
  * Instances of this class are made by the {@link RunnableManager} passing a
- * configuration into the <code>configure</code> method.
- *
+ * threadpool into the <code>init</code> method.
+ * 
+ * <pre>
+ *   &lt;!--+
+ *       | More indepth information can be found at
+ *       | http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/PooledExecutor.html
+ *       | The following elements can be used:
+ *       +--&gt;
+ *   &lt;!-- required name of the pool --&gt;
+ *   &lt;property name=&quot;name&quot; value=&quot;default&quot; /&gt;
+ *   &lt;!--+
+ *       | optional priority all threads of the pool will have (the ThreadFactory will be 
+ *       | set to this priority).The possible values  are:
+ *       |    MIN:  corresponds to Thread#MIN_PRIORITY
+ *       |    NORM: corresponds to Thread#NORM_PRIORITY (default)
+ *       |    MAX:  corresponds to Thread#MAX_PRIORITY
+ *       +--&gt;
+ *   &lt;property name=&quot;poolPriority&quot; value=&quot;NORM&quot; /&gt;
+ *   &lt;!--+
+ *       | whether newly created Threads should run in daemon mode or not. Default to false.
+ *       +--&gt;
+ *   &lt;property name=&quot;daemon&quot; value=&quot;false&quot; /&gt;
+ *   &lt;!--+ 
+ *       | optional size of a queue to hold Runnables if the pool is full. Possible values are:
+ *      |    less than 0:    unbounded (default)
+ *       |    equal to 0:     no queue at all
+ *       |    greater than 0: size of the queue
+ *    --&gt;
+ *   &lt;property name=&quot;queueSize&quot; value=&quot;-1&quot; /&gt;
+ *   &lt;!--+
+ *       | optional maximum number of threads in the pool. Defaults to 5.
+ *       | NOTE: if a queue is specified (queue-sie != 0)
+ *       |       this value will be ignored.
+ *       +--&gt;
+ *   &lt;property name=&quot;maxPoolSize&quot; value=&quot;5&quot; /&gt;
+ *   &lt;!--+
+ *       | optional minimum number of threads in the pool. Defaults to 5.
+ *       | NOTE: if a queue has been specified (queue-sie != 0)
+ *       |       this value will be used as the maximum of thread running concurrently.
+ *       +--&gt;
+ *   &lt;property name=&quot;minPoolSize&quot; value=&quot;5&quot; /&gt;
+ *   &lt;!--+
+ *       | The time in ms an idle thread should keep alive before it might get garbage collected.
+ *       | This defaults to 60000 ms.
+ *       +--&gt;
+ *   &lt;property name=&quot;keepAliveTime&quot; value=&quot;60000&quot; /&gt;
+ *   &lt;!--+
+ *       | The policy to be used if all resources (thread in the pool and 
+ *       | slots in the queue) are exhausted.
+ *       | Possible values are:
+ *       |    ABORT:         Throw a RuntimeException
+ *       |    DISCARD:       Throw away the current request and return.
+ *       |    DISCARDOLDEST: Throw away the oldest request and return.
+ *       |    RUN (default): The thread making the execute request runs the task itself.
+ *       |                   This policy helps guard against lockup.
+ *       |    WAIT:          Wait until a thread becomes available. This policy should, in
+ *       |                   general, not be used if the minimum number of threads is zero,
+ *       |                   in which case a thread may never become available. 
+ *       +--&gt;
+ *   &lt;property name=&quot;blockPolicy&quot; value=&quot;ABORT&quot; /&gt;
+ *   &lt;!--+
+ *       | Terminate thread pool after processing all Runnables currently in queue. Any 
+ *       | Runnable entered after this point will be discarded. A shut down pool cannot 
+ *       | be restarted. This also means that a pool will need keep-alive-time-ms to 
+ *       | terminate. The default value not to shutdown graceful. 
+ *       +--&gt;
+ *   &lt;property name=&quot;shutdownGraceful&quot; value=&quot;false&quot; /&gt;
+ *   &lt;!--+
+ *       | The time in ms to wait before issuing an immediate shutdown after a graceful shutdown
+ *       | has been requested. 
+ *       +--&gt;
+ *   &lt;property name=&quot;shutdownWaitTimeMs&quot; value=&quot;-1&quot; /&gt;
+ *   &lt;!--+
+ *       | specifies the fully qualified class name of an org.apache.cocoon.components.thread.ThreadFactory
+ *       | implementation. It is responsible to create Thread classes.
+ *       +--&gt;
+ *   &lt;property name=&quot;factory&quot; ref=&quot;defaultThreadFactory&quot;/&gt;
+ * </pre>
+ * 
  * @version $Id$
  */
-public class DefaultThreadPool
-    extends PooledExecutor
-    implements ThreadPool {
+public class DefaultThreadPool extends PooledExecutor implements
+	InitializingBean, ThreadPool {
 
-    //~ Static fields/initializers ---------------------------------------------
+    // ~ Static fields/initializers
+    // ---------------------------------------------
 
     /** Default ThreadPool block policy */
     public static final String POLICY_DEFAULT = POLICY_RUN;
 
-    //~ Instance fields --------------------------------------------------------
-
-    /** Wrapps a channel */
-    private ChannelWrapper channelWrapper;
-
     /** By default we use the logger for this class. */
-    private Log logger = LogFactory.getLog(getClass());
-
-    /** The Queue */
-    private Queue queue;
+    protected final Log logger = LogFactory.getLog(getClass());
 
-    /** The blocking policy */
-    private String blockPolicy;
+    // ~ Instance fields
+    // --------------------------------------------------------
 
     /** The name of this thread pool */
-    private String name;
+    private String name = ThreadPool.DEFAULT_THREADPOOL_NAME;
 
-    /** Should we wait for running jobs to terminate on shutdown ? */
-    private boolean shutdownGraceful;
+    /** Is daemon thread pool */
+    private boolean daemon = ThreadPool.DEFAULT_DAEMON_MODE;
+
+    /** The priority of this thread pool */
+    private int priority = convertPriority(ThreadPool.DEFAULT_THREAD_PRIORITY);
 
     /** The maximum queue size */
-    private int queueSize;
+    private int queueSize = ThreadPool.DEFAULT_QUEUE_SIZE;
+
+    /** The maximum pool size */
+    private int maxPoolSize = ThreadPool.DEFAULT_MAX_POOL_SIZE;
+
+    /** The minimum pool size */
+    private int minPoolSize = ThreadPool.DEFAULT_MIN_POOL_SIZE;
+
+    /** The keep alive time in milliseconds */
+    private long keepAliveTime = ThreadPool.DEFAULT_KEEP_ALIVE_TIME;
+
+    /** The blocking policy */
+    private String blockPolicy = ThreadPool.DEFAULT_BLOCK_POLICY;
+
+    /** Should we wait for running jobs to terminate on shutdown ? */
+    private boolean shutdownGraceful = ThreadPool.DEFAULT_SHUTDOWN_GRACEFUL;
 
     /** How long to wait for running jobs to terminate on disposition */
-    private int shutdownWaitTimeMs;
+    private int shutdownWaitTimeMs = ThreadPool.DEFAULT_SHUTDOWN_WAIT_TIME;
+
+    /** A ThreadFactory implementation */
+    private ThreadFactory factory;
+
+    /** Wrapps a channel */
+    private ChannelWrapper channelWrapper;
+
+    /** The Queue */
+    private Queue queue;
 
-    //~ Constructors -----------------------------------------------------------
+    // ~ Constructors
+    // -----------------------------------------------------------
 
     /**
-     * Create a new pool.
-     */
-    DefaultThreadPool() {
-        this( new ChannelWrapper() );
+         * Create a new pool.
+         * 
+         * @param channel
+         *                DOCUMENT ME!
+         */
+    private DefaultThreadPool(final ChannelWrapper channel) {
+	super(channel);
+	channelWrapper = channel;
     }
 
     /**
-     * Create a new pool.
-     *
-     * @param channel DOCUMENT ME!
-     */
-    private DefaultThreadPool( final ChannelWrapper channel ) {
-        super( channel );
-        channelWrapper = channel;
+         * Create a new pool.
+         */
+    DefaultThreadPool() {
+	this(new ChannelWrapper());
     }
 
-    //~ Methods ----------------------------------------------------------------
-
-    public Log getLogger() {
-        return this.logger;
-    }
+    // ~ Methods
+    // ----------------------------------------------------------------
 
-    public void setLogger(Log l) {
-        this.logger = l;
+    /** Initialize the bean after properties set */
+    public void afterPropertiesSet() throws IllegalArgumentException {
+	if (logger.isInfoEnabled()) {
+	    logger.info("ThreadPool [" + name + "] initializing ...");
+	}
+
+	initFactory();
+	super.setThreadFactory(factory);
+	initMinPoolSize();
+	initPriority();
+	initDaemon();
+	initQueueSize();
+	initMaxPoolSize();
+	initKeepAliveTime();
+
+	if (logger.isInfoEnabled()) {
+	    logger.info(this.toString());
+	    logger.info("ThreadPool [" + name + "] initialized");
+	}
     }
 
     /**
-     * DOCUMENT ME!
-     *
-     * @return Returns the blockPolicy.
-     */
+         * Get the block policy
+         * 
+         * @return Returns the blockPolicy.
+         */
     public String getBlockPolicy() {
-        return blockPolicy;
+	return blockPolicy;
     }
 
     /**
-     * DOCUMENT ME!
-     *
-     * @return maximum size of the queue (0 if isQueued() == false)
-     *
-     * @see org.apache.cocoon.components.thread.ThreadPool#getQueueSize()
-     */
+         * DOCUMENT ME!
+         * 
+         * @return maximum size of the queue (0 if isQueued() == false)
+         * 
+         * @see org.apache.cocoon.components.thread.ThreadPool#getQueueSize()
+         */
     public int getMaxQueueSize() {
-        return ( ( queueSize < 0 ) ? Integer.MAX_VALUE : queueSize );
-    }
-
-    /**
-     * DOCUMENT ME!
-     *
-     * @return size of queue (0 if isQueued() == false)
-     *
-     * @see org.apache.cocoon.components.thread.ThreadPool#getQueueSize()
-     */
-    public int getMaximumQueueSize() {
-        return queueSize;
+	return ((queueSize < 0) ? Integer.MAX_VALUE : queueSize);
     }
 
     /**
-     * @see org.apache.cocoon.components.thread.ThreadPool#getName()
-     */
+         * @see org.apache.cocoon.components.thread.ThreadPool#getName()
+         */
     public String getName() {
-        return name;
+	return name;
     }
 
     /**
-     * Get hte priority used to create Threads
-     *
-     * @return {@link Thread#MIN_PRIORITY}, {@link Thread#NORM_PRIORITY}, or
-     *         {@link Thread#MAX_PRIORITY}
-     */
+         * Get hte priority used to create Threads
+         * 
+         * @return {@link Thread#MIN_PRIORITY}, {@link Thread#NORM_PRIORITY},
+         *         or {@link Thread#MAX_PRIORITY}
+         */
     public int getPriority() {
-        return ((ThreadFactory)super.getThreadFactory()).getPriority();
+	return ((ThreadFactory) super.getThreadFactory()).getPriority();
     }
 
     /**
-     * DOCUMENT ME!
-     *
-     * @return current size of the queue (0 if isQueued() == false)
-     *
-     * @see org.apache.cocoon.components.thread.ThreadPool#getQueueSize()
-     */
+         * DOCUMENT ME!
+         * 
+         * @return current size of the queue (0 if isQueued() == false)
+         * 
+         * @see org.apache.cocoon.components.thread.ThreadPool#getQueueSize()
+         */
     public int getQueueSize() {
-        return queue.getQueueSize();
+	return queue.getQueueSize();
     }
 
     /**
-     * Whether this DefaultThreadPool has a queue
-     *
-     * @return Returns the m_isQueued.
-     *
-     * @see org.apache.cocoon.components.thread.ThreadPool#isQueued()
-     */
+         * Whether this DefaultThreadPool has a queue
+         * 
+         * @return Returns the m_isQueued.
+         * 
+         * @see org.apache.cocoon.components.thread.ThreadPool#isQueued()
+         */
     public boolean isQueued() {
-        return queueSize != 0;
+	return queueSize != 0;
     }
 
     /**
-     * Execute a command
-     *
-     * @param command The {@link Runnable} to execute
-     *
-     * @throws InterruptedException In case of interruption
-     */
-    public void execute( Runnable command ) throws InterruptedException {
-        if( getLogger().isDebugEnabled() ) {
-            getLogger().debug( "Executing Command: " + command.toString() +
-                                 ",pool=" + getName() );
-        }
+         * Execute a command
+         * 
+         * @param command
+         *                The {@link Runnable} to execute
+         * 
+         * @throws InterruptedException
+         *                 In case of interruption
+         */
+    public void execute(Runnable command) throws InterruptedException {
+	if (logger.isDebugEnabled()) {
+	    logger.debug("Executing Command: " + command.toString() + ",pool="
+		    + getName());
+	}
 
-        super.execute( command );
+	super.execute(command);
     }
 
     /**
-     * @see org.apache.cocoon.components.thread.ThreadPool#shutdown()
-     */
+         * @see org.apache.cocoon.components.thread.ThreadPool#shutdown()
+         */
     public void shutdown() {
-        if( shutdownGraceful ) {
-            shutdownAfterProcessingCurrentlyQueuedTasks();
-        } else {
-            shutdownNow();
-        }
-
-        try {
-            if( getShutdownWaitTimeMs() > 0 ) {
-                if( ! awaitTerminationAfterShutdown( getShutdownWaitTimeMs()) ) {
-                    getLogger().warn( "running commands have not terminated within " +
-                                      getShutdownWaitTimeMs() +
-                                      "ms. Will shut them down by interruption" );
-                    interruptAll();
-                    shutdownNow();
-                }
-            }
-
-            awaitTerminationAfterShutdown();
-        } catch( final InterruptedException ie ) {
-            getLogger().error( "cannot shutdown ThreadPool", ie );
-        }
-    }
-
-    /**
-     * Set the blocking policy
-     *
-     * @param blockPolicy The blocking policy value
-     */
-    void setBlockPolicy( final String blockPolicy ) {
-        this.blockPolicy = blockPolicy;
-
-        if( POLICY_ABORT.equalsIgnoreCase( blockPolicy ) ) {
-            abortWhenBlocked(  );
-        } else if( POLICY_DISCARD.equalsIgnoreCase( blockPolicy ) ) {
-            discardWhenBlocked(  );
-        } else if( POLICY_DISCARD_OLDEST.equalsIgnoreCase( blockPolicy ) ) {
-            discardOldestWhenBlocked();
-        } else if( POLICY_RUN.equalsIgnoreCase( blockPolicy ) ) {
-            runWhenBlocked();
-        } else if( POLICY_WAIT.equalsIgnoreCase( blockPolicy ) ) {
-            waitWhenBlocked();
-        } else {
-            final StringBuffer msg = new StringBuffer();
-            msg.append( "WARNING: Unknown block-policy configuration \"" )
-               .append( blockPolicy );
-            msg.append( "\". Should be one of \"" ).append( POLICY_ABORT );
-            msg.append( "\",\"" ).append( POLICY_DISCARD );
-            msg.append( "\",\"" ).append( POLICY_DISCARD_OLDEST );
-            msg.append( "\",\"" ).append( POLICY_RUN );
-            msg.append( "\",\"" ).append( POLICY_WAIT );
-            msg.append( "\". Will use \"" ).append( POLICY_DEFAULT ).append( "\"" );
-            getLogger().warn( msg.toString() );
-            setBlockPolicy( POLICY_DEFAULT );
-        }
-    }
-
-    /**
-     * DOCUMENT ME!
-     *
-     * @param name The name to set.
-     */
-    void setName( String name ) {
-        this.name = name;
-    }
-
-    /**
-     * DOCUMENT ME!
-     *
-     * @param queueSize DOCUMENT ME!
-     */
-    void setQueue( final int queueSize ) {
-        if( queueSize != 0 ) {
-            if( queueSize > 0 ) {
-                queue = new BoundedQueue( queueSize );
-            } else {
-                queue = new LinkedQueue(  );
-            }
-        } else {
-            queue = new SynchronousChannel(  );
-        }
-
-        this.queueSize = queueSize;
-        channelWrapper.setChannel( queue );
-    }
-
-    /**
-     * DOCUMENT ME!
-     *
-     * @param shutdownGraceful The shutdownGraceful to set.
-     */
-    void setShutdownGraceful( boolean shutdownGraceful ) {
-        this.shutdownGraceful = shutdownGraceful;
-    }
-
-    /**
-     * DOCUMENT ME!
-     *
-     * @return Returns the shutdownGraceful.
-     */
-    boolean isShutdownGraceful() {
-        return shutdownGraceful;
-    }
-
-    /**
-     * DOCUMENT ME!
-     *
-     * @param shutdownWaitTimeMs The shutdownWaitTimeMs to set.
-     */
-    void setShutdownWaitTimeMs( int shutdownWaitTimeMs ) {
-        this.shutdownWaitTimeMs = shutdownWaitTimeMs;
-    }
-
-    /**
-     * DOCUMENT ME!
-     *
-     * @return Returns the shutdownWaitTimeMs.
-     */
-    int getShutdownWaitTimeMs() {
-        return shutdownWaitTimeMs;
+	if (shutdownGraceful) {
+	    shutdownAfterProcessingCurrentlyQueuedTasks();
+	} else {
+	    shutdownNow();
+	}
+
+	try {
+	    if (getShutdownWaitTimeMs() > 0) {
+		if (!awaitTerminationAfterShutdown(getShutdownWaitTimeMs())) {
+		    logger.warn("running commands have not terminated within "
+			    + getShutdownWaitTimeMs()
+			    + "ms. Will shut them down by interruption");
+		    interruptAll();
+		    shutdownNow();
+		}
+	    }
+
+	    awaitTerminationAfterShutdown();
+	} catch (final InterruptedException ie) {
+	    logger.error("cannot shutdown ThreadPool", ie);
+	}
+    }
+
+    /**
+         * Set the blocking policy
+         * 
+         * @param blockPolicy
+         *                The blocking policy value
+         */
+    public void setBlockPolicy(final String blockPolicy) {
+	this.blockPolicy = blockPolicy;
+
+	if (POLICY_ABORT.equalsIgnoreCase(blockPolicy)) {
+	    abortWhenBlocked();
+	} else if (POLICY_DISCARD.equalsIgnoreCase(blockPolicy)) {
+	    discardWhenBlocked();
+	} else if (POLICY_DISCARD_OLDEST.equalsIgnoreCase(blockPolicy)) {
+	    discardOldestWhenBlocked();
+	} else if (POLICY_RUN.equalsIgnoreCase(blockPolicy)) {
+	    runWhenBlocked();
+	} else if (POLICY_WAIT.equalsIgnoreCase(blockPolicy)) {
+	    waitWhenBlocked();
+	} else {
+	    final StringBuffer msg = new StringBuffer();
+	    msg.append("WARNING: Unknown block-policy configuration \"")
+		    .append(blockPolicy);
+	    msg.append("\". Should be one of \"").append(POLICY_ABORT);
+	    msg.append("\",\"").append(POLICY_DISCARD);
+	    msg.append("\",\"").append(POLICY_DISCARD_OLDEST);
+	    msg.append("\",\"").append(POLICY_RUN);
+	    msg.append("\",\"").append(POLICY_WAIT);
+	    msg.append("\". Will use \"").append(POLICY_DEFAULT).append("\"");
+	    logger.warn(msg.toString());
+	    setBlockPolicy(POLICY_DEFAULT);
+	}
+    }
+
+    /**
+         * DOCUMENT ME!
+         * 
+         * @param name
+         *                The name to set.
+         */
+    public void setName(String name) {
+	this.name = name;
+    }
+
+    /**
+         * DOCUMENT ME!
+         * 
+         * @param shutdownGraceful
+         *                The shutdownGraceful to set.
+         */
+    public void setShutdownGraceful(boolean shutdownGraceful) {
+	this.shutdownGraceful = shutdownGraceful;
+    }
+
+    /**
+         * DOCUMENT ME!
+         * 
+         * @return Returns the shutdownGraceful.
+         */
+    public boolean isShutdownGraceful() {
+	return shutdownGraceful;
+    }
+
+    /**
+         * DOCUMENT ME!
+         * 
+         * @param shutdownWaitTimeMs
+         *                The shutdownWaitTimeMs to set.
+         */
+    public void setShutdownWaitTimeMs(int shutdownWaitTimeMs) {
+	this.shutdownWaitTimeMs = shutdownWaitTimeMs;
+    }
+
+    /**
+         * DOCUMENT ME!
+         * 
+         * @return Returns the shutdownWaitTimeMs.
+         */
+    public int getShutdownWaitTimeMs() {
+	return shutdownWaitTimeMs;
+    }
+
+    /**
+         * @return the keepAliveTime
+         */
+    public long getKeepAliveTime() {
+	return keepAliveTime;
+    }
+
+    /**
+         * @param keepAliveTime
+         *                the keepAliveTime to set
+         */
+    public void setKeepAliveTime(long keepAliveTime) {
+	this.keepAliveTime = keepAliveTime;
+    }
+
+    /**
+         * @return the maxPoolSize
+         */
+    public int getMaxPoolSize() {
+	return maxPoolSize;
+    }
+
+    /**
+         * @param maxPoolSize
+         *                the maxPoolSize to set
+         */
+    public void setMaxPoolSize(int maxPoolSize) {
+	this.maxPoolSize = maxPoolSize;
+    }
+
+    /**
+         * @return the minPoolSize
+         */
+    public int getMinPoolSize() {
+	return minPoolSize;
+    }
+
+    /**
+         * @param minPoolSize
+         *                the minPoolSize to set
+         */
+    public void setMinPoolSize(int minPoolSize) {
+	this.minPoolSize = minPoolSize;
+    }
+
+    /**
+         * @return the threadFactory
+         */
+    public ThreadFactory getFactory() {
+	return factory;
+    }
+
+    /**
+         * @param priority
+         *                the priority to set
+         */
+    public void setPriority(int priority) {
+	this.priority = priority;
+    }
+
+    /**
+         * @param pool
+         *                priority the priority to set
+         */
+    public void setPoolPriority(String poolPriority) {
+	setPriority(convertPriority(poolPriority));
+    }
+
+    /**
+         * Sets the queue size of the thread pool
+         * 
+         * @param queueSize
+         *                the queueSize to set
+         */
+    public void setQueueSize(int queueSize) {
+	this.queueSize = queueSize;
+    }
+
+    /**
+         * Returns true if thread runs as daemon
+         * 
+         * @return the daemon
+         */
+    public boolean isDaemon() {
+	return daemon;
+    }
+
+    /**
+         * Set to true if thread shall run as daemon
+         * 
+         * @param daemon
+         *                the daemon to set
+         */
+    public void setDaemon(boolean daemon) {
+	this.daemon = daemon;
+    }
+
+    /**
+         * Overwrite the toString method
+         */
+    public String toString() {
+	if (this.isQueued()) {
+	    final StringBuffer msg = new StringBuffer();
+	    msg.append("ThreadPool named \"").append(name);
+	    msg.append("\" created with maximum queue-size=").append(queueSize);
+	    msg.append(",max-pool-size=").append(maximumPoolSize_);
+	    msg.append(",min-pool-size=").append(minimumPoolSize_);
+	    msg.append(",priority=").append(priority);
+	    msg.append(",isDaemon=").append(
+		    ((ThreadFactory) this.getThreadFactory()).isDaemon());
+	    msg.append(",keep-alive-time-ms=").append(keepAliveTime_);
+	    msg.append(",block-policy=\"").append(blockPolicy);
+	    msg.append("\",shutdown-wait-time-ms=").append(shutdownWaitTimeMs);
+	    return msg.toString();
+	} else {
+	    final StringBuffer msg = new StringBuffer();
+	    msg.append("ThreadPool named \"").append(name);
+	    msg.append("\" created with no queue,max-pool-size=").append(
+		    maximumPoolSize_);
+	    msg.append(",min-pool-size=").append(minimumPoolSize_);
+	    msg.append(",priority=").append(priority);
+	    msg.append(",isDaemon=").append(
+		    ((ThreadFactory) this.getThreadFactory()).isDaemon());
+	    msg.append(",keep-alive-time-ms=").append(keepAliveTime_);
+	    msg.append(",block-policy=").append(blockPolicy);
+	    msg.append(",shutdown-wait-time-ms=").append(shutdownWaitTimeMs);
+	    return msg.toString();
+	}
+    }
+
+    /**
+         * DOCUMENT ME!
+         * 
+         * @param priority
+         *                The priority to set as string value.
+         * 
+         * @return The priority as int value.
+         */
+    private int convertPriority(final String priority) {
+	if ("MIN".equalsIgnoreCase(priority)) {
+	    return Thread.MIN_PRIORITY;
+	} else if ("NORM".equalsIgnoreCase(priority)) {
+	    return Thread.NORM_PRIORITY;
+	} else if ("MAX".equalsIgnoreCase(priority)) {
+	    return Thread.MAX_PRIORITY;
+	} else {
+	    logger.warn("Unknown thread priority \"" + priority
+		    + "\". Set to \"NORM\".");
+
+	    return Thread.NORM_PRIORITY;
+	}
+    }
+
+    /**
+         * @param factory
+         *                the factory to set
+         */
+    public void setFactory(ThreadFactory factory) {
+	this.factory = factory;
+    }
+
+    private void initFactory() {
+	if (factory == null) {
+	    logger.warn("No ThreadFactory is configured. Will use a "
+		    + DefaultThreadFactory.class.getName());
+	    factory = new org.apache.cocoon.components.thread.DefaultThreadFactory();
+	}
+    }
+
+    private void initMinPoolSize() {
+	// Min pool size
+	// make sure we have enough threads for the default thread pool as we
+	// need one for ourself
+	if (ThreadPool.DEFAULT_THREADPOOL_NAME.equals(name)
+		&& ((minPoolSize > 0) && (minPoolSize < ThreadPool.DEFAULT_MIN_POOL_SIZE))) {
+	    minPoolSize = ThreadPool.DEFAULT_MIN_POOL_SIZE;
+	}
+	if (minPoolSize < 1) {
+	    minPoolSize = (minPoolSize < 1) ? 1 : minPoolSize;
+	    logger
+		    .warn("min-pool-size < 1 for pool \"" + name
+			    + "\". Set to 1");
+	}
+	super.setMinimumPoolSize(minPoolSize);
+    }
+
+    private void initPriority() {
+	// Use priority from factory when changed
+	priority = (factory.getPriority() != Thread.NORM_PRIORITY ? factory
+		.getPriority() : priority);
+	factory.setPriority(priority);
+    }
+
+    private void initDaemon() {
+	// Use daemon from factory when changed
+	daemon = (factory.isDaemon() != false ? factory.isDaemon() : daemon);
+	factory.setDaemon(daemon);
+    }
+
+    private void initMaxPoolSize() {
+	// Max pool size
+	maxPoolSize = (maxPoolSize < 0) ? Integer.MAX_VALUE : maxPoolSize;
+	super.setMaximumPoolSize(maxPoolSize);
+    }
+
+    private void initKeepAliveTime() {
+	// Keep alive time
+	if (keepAliveTime < 0) {
+	    keepAliveTime = 1000;
+	    logger.warn("keep-alive-time-ms < 0 for pool \"" + name
+		    + "\". Set to 1000");
+	}
+	super.setKeepAliveTime(keepAliveTime);
+    }
+
+    private void initQueueSize() {
+	if (queueSize != 0) {
+	    if (queueSize > 0) {
+		queue = new BoundedQueue(queueSize);
+	    } else {
+		queue = new LinkedQueue();
+	    }
+	} else {
+	    queue = new SynchronousChannel();
+	}
+	channelWrapper.setChannel(queue);
     }
 }

Modified: cocoon/trunk/core/cocoon-thread/cocoon-thread-impl/src/main/resources/META-INF/cocoon/spring/cocoon-thread-impl.xml
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-thread/cocoon-thread-impl/src/main/resources/META-INF/cocoon/spring/cocoon-thread-impl.xml?view=diff&rev=522946&r1=522945&r2=522946
==============================================================================
--- cocoon/trunk/core/cocoon-thread/cocoon-thread-impl/src/main/resources/META-INF/cocoon/spring/cocoon-thread-impl.xml (original)
+++ cocoon/trunk/core/cocoon-thread/cocoon-thread-impl/src/main/resources/META-INF/cocoon/spring/cocoon-thread-impl.xml Tue Mar 27 08:10:39 2007
@@ -19,8 +19,10 @@
 <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:util="http://www.springframework.org/schema/util"
+       xmlns:configurator="http://cocoon.apache.org/schema/configurator"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
-                           http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd">
+                           http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd
+                           http://cocoon.apache.org/schema/configurator http://cocoon.apache.org/schema/configurator/cocoon-configurator-1.0.1.xsd">
 
   <!--+
       | Runnable manager
@@ -30,108 +32,118 @@
       +-->
   <bean name="org.apache.cocoon.components.thread.RunnableManager"
         class="org.apache.cocoon.components.thread.DefaultRunnableManager"
-        scope="singleton" init-method="init" destroy-method="destroy">
+        scope="singleton" destroy-method="destroy">
     <!--+
         | This is the default configuration of the runnable-manager. More
         | indepth information can be found at
         | http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/PooledExecutor.html
         | The following elements can be used:
         |
-        | thread-factory:        specifies the fully qualified class name of an
-        |                        org.apache.cocoon.components.thread.ThreadFactory
-        |                        implementation. It is responsible to create Thread
-        |                        classes.
-        | thread-pools:          container element for thread-pool elements.
-        | name:                  required name of the pool.
-        | priority:              optional priority all threads of the pool will
-        |                        have (the ThreadFactory will be set to this
-        |                        priority).The possible values  are:
-        |                          MIN:  corresponds to Thread#MIN_PRIORITY
-        |                          NORM: corresponds to Thread#NORM_PRIORITY (default)
-        |                          MAX:  corresponds to Thread#MAX_PRIORITY
-        | daemon:                whether newly created Threads should run in
-        |                        daemon mode or not. Default to false.
-        | queue-size:            optional size of a queue to hold Runnables if the
-        |                        pool is full. Possible values are:
-        |                          less than 0:    unbounded (default)
-        |                          equal to 0:     no queue at all
-        |                          greater than 0: size of the queue
-        | max-pool-size:         optional maximum number of threads in the pool.
-        |                        Defaults to 5.
-        |                        NOTE: if a queue is specified (queue-sie != 0)
-        |                              this value will be ignored.
-        | min-pool-size:         optional minimum number of threads in the pool.
-        |                        Defaults to 5.
-        |                        NOTE: if a queue has been specified (queue-sie != 0)
-        |                              this value will be used as the maximum of
-        |                              thread running concurrently.
-        | keep-alive-time-ms:    The time in ms an idle thread should keep alive
-        |                        before it might get garbage collected. This
-        |                        defaults to 60000 ms.
-        | block-policy;          The policy to be used if all resources (thread in
-        |                        the pool and slots in the queue) are exhausted.
-        |                        Possible values are:
-        |                          ABORT:         Throw a RuntimeException
-        |                          DISCARD:       Throw away the current request
-        |                                         and return.
-        |                          DISCARDOLDEST: Throw away the oldest request
-        |                                         and return.
-        |                          RUN (default): The thread making the execute
-        |                                         request runs the task itself.
-        |                                         This policy helps guard against
-        |                                         lockup.
-        |                          WAIT:          Wait until a thread becomes
-        |                                         available. This policy should, in
-        |                                         general, not be used if the
-        |                                         minimum number of threads is zero,
-        |                                         in which case a thread may never
-        |                                         become available.
-        | shutdown-graceful:     Terminate thread pool after processing all
-        |                        Runnables currently in queue. Any Runnable entered
-        |                        after this point will be discarded. A shut down
-        |                        pool cannot be restarted. This also means that a
-        |                        pool will need keep-alive-time-ms to terminate.
-        |                        The default value not to shutdown graceful.
-        | shutdown-wait-time-ms: The time in ms to wait before issuing an
-        |                        immediate shutdown after a graceful shutdown
-        |                        has been requested.
-        +-->
-    <property name="threadFactory" value="org.apache.cocoon.components.thread.DefaultThreadFactory"/>
-    <property name="threadPools">
-      <list>
-        <!--+
-            | This is the default thread pool. It's use fits best for short
-            | running background tasks.
-            +-->
-        <map>
-          <entry key="name" value="default"/>
-          <entry key="priority" value="NORM"/>
-          <entry key="daemon" value="false"/>
-          <entry key="queue-size" value="-1"/>
-          <entry key="max-pool-size" value="5"/>
-          <entry key="min-pool-size" value="5"/>
-          <entry key="keep-alive-time-ms" value="60000"/>
-          <entry key="block-policy" value="ABORT"/>
-          <entry key="shutdown-graceful" value="false"/>
-          <entry key="shutdown-wait-time-ms" value="-1"/>
-        </map>
-        <!--+
-            | This thread pool should be used for daemons (permanently running
-            | threads).
-            +-->
-        <map>
-          <entry key="name" value="daemon"/>
-          <entry key="priority" value="NORM"/>
-          <entry key="daemon" value="true"/>
-          <entry key="queue-size" value="0"/>
-          <entry key="max-pool-size" value="-1"/>
-          <entry key="min-pool-size" value="1"/>
-          <entry key="keep-alive-time-ms" value="60000"/>
-          <entry key="block-policy" value="ABORT"/>
-          <entry key="shutdown-graceful" value="false"/>
-          <entry key="shutdown-wait-time-ms" value="-1"/>
-        </map>
-      </list>
+        | threadPools:       container element for thread-pool elements.
+        +-->
+    <property name="workerThreadPools">
+      <configurator:bean-map type="org.apache.cocoon.components.thread.ThreadPool" strip-prefix="true"/>
     </property>
   </bean>
+  
+  <!--+
+      | This is the default thread pool. It's use fits best for short
+      | running background tasks.
+      +-->
+  <bean name="org.apache.cocoon.components.thread.ThreadPool/default" class="org.apache.cocoon.components.thread.DefaultThreadPool" scope="singleton">
+    <!--+
+        | More indepth information can be found at
+        | http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/PooledExecutor.html
+        | The following elements can be used:
+        +-->
+    <!-- required name of the pool -->
+    <property name="name" value="default" />
+    <!--+
+        | optional priority all threads of the pool will have (the ThreadFactory will be 
+        | set to this priority).The possible values  are:
+        |    MIN:  corresponds to Thread#MIN_PRIORITY
+        |    NORM: corresponds to Thread#NORM_PRIORITY (default)
+        |    MAX:  corresponds to Thread#MAX_PRIORITY
+        +-->
+    <property name="poolPriority" value="NORM" />
+    <!--+
+        | whether newly created Threads should run in daemon mode or not. Default to false.
+        +-->
+    <property name="daemon" value="false" />
+    <!-- 
+        | optional size of a queue to hold Runnables if the pool is full. Possible values are:
+        |    less than 0:    unbounded (default)
+        |    equal to 0:     no queue at all
+        |    greater than 0: size of the queue
+     -->
+    <property name="queueSize" value="-1" />
+    <!--+
+        | optional maximum number of threads in the pool. Defaults to 5.
+        | NOTE: if a queue is specified (queue-sie != 0)
+        |       this value will be ignored.
+        +-->
+    <property name="maxPoolSize" value="5" />
+    <!--+
+        | optional minimum number of threads in the pool. Defaults to 5.
+        | NOTE: if a queue has been specified (queue-sie != 0)
+        |       this value will be used as the maximum of thread running concurrently.
+        +-->
+    <property name="minPoolSize" value="5" />
+    <!--+
+        | The time in ms an idle thread should keep alive before it might get garbage collected.
+        | This defaults to 60000 ms.
+        +-->
+    <property name="keepAliveTime" value="60000" />
+    <!--+
+        | The policy to be used if all resources (thread in the pool and 
+        | slots in the queue) are exhausted.
+        | Possible values are:
+        |    ABORT:         Throw a RuntimeException
+        |    DISCARD:       Throw away the current request and return.
+        |    DISCARDOLDEST: Throw away the oldest request and return.
+        |    RUN (default): The thread making the execute request runs the task itself.
+        |                   This policy helps guard against lockup.
+        |    WAIT:          Wait until a thread becomes available. This policy should, in
+        |                   general, not be used if the minimum number of threads is zero,
+        |                   in which case a thread may never become available. 
+        +-->
+    <property name="blockPolicy" value="ABORT" />
+    <!--+
+        | Terminate thread pool after processing all Runnables currently in queue. Any 
+        | Runnable entered after this point will be discarded. A shut down pool cannot 
+        | be restarted. This also means that a pool will need keep-alive-time-ms to 
+        | terminate. The default value not to shutdown graceful. 
+        +-->
+    <property name="shutdownGraceful" value="false" />
+    <!--+
+        | The time in ms to wait before issuing an immediate shutdown after a graceful shutdown
+        | has been requested. 
+        +-->
+    <property name="shutdownWaitTimeMs" value="-1" />
+    <!--+
+        | specifies the fully qualified class name of an org.apache.cocoon.components.thread.ThreadFactory
+        | implementation. It is responsible to create Thread classes.
+        +-->
+    <property name="factory" ref="defaultThreadFactory"/>
+  </bean>
+
+  <!--+
+      | This thread pool should be used for daemons (permanently running
+      | threads).
+      +-->
+  <bean name="org.apache.cocoon.components.thread.ThreadPool/daemon" class="org.apache.cocoon.components.thread.DefaultThreadPool" scope="singleton">
+    <property name="name" value="daemon"/>
+    <property name="poolPriority" value="NORM"/>
+    <property name="daemon" value="true"/>
+    <property name="queueSize" value="0"/>
+    <property name="maxPoolSize" value="-1"/>
+    <property name="minPoolSize" value="1"/>
+    <property name="keepAliveTime" value="60000"/>
+    <property name="blockPolicy" value="ABORT"/>
+    <property name="shutdownGraceful" value="false"/>
+    <property name="shutdownWaitTimeMs" value="-1"/>
+    <property name="factory" ref="defaultThreadFactory"/>
+  </bean>
+  
+  <bean id="defaultThreadFactory" class="org.apache.cocoon.components.thread.DefaultThreadFactory" scope="prototype" />
 </beans>

Modified: cocoon/trunk/core/cocoon-thread/cocoon-thread-impl/src/test/java/org/apache/cocoon/components/thread/DefaultThreadPoolTestCase.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-thread/cocoon-thread-impl/src/test/java/org/apache/cocoon/components/thread/DefaultThreadPoolTestCase.java?view=diff&rev=522946&r1=522945&r2=522946
==============================================================================
--- cocoon/trunk/core/cocoon-thread/cocoon-thread-impl/src/test/java/org/apache/cocoon/components/thread/DefaultThreadPoolTestCase.java (original)
+++ cocoon/trunk/core/cocoon-thread/cocoon-thread-impl/src/test/java/org/apache/cocoon/components/thread/DefaultThreadPoolTestCase.java Tue Mar 27 08:10:39 2007
@@ -22,122 +22,120 @@
 
 /**
  * The $classType$ class ...
- *
- * @version $Id$
+ * 
+ * @version $Id: DefaultThreadPoolTestCase.java 494399 2007-01-09 13:10:08Z
+ *          cziegeler $
  */
-public class DefaultThreadPoolTestCase
-    extends AbstractTestCase {
-
-    //~ Methods ----------------------------------------------------------------
+public class DefaultThreadPoolTestCase extends AbstractTestCase {
 
     /**
-     * DOCUMENT ME!
-     */
-    public final void testDefaultThreadPool(  )
-    {
-        final DefaultThreadPool pool = new DefaultThreadPool(  );
-        pool.setName( "mypool" );
-
-        // We cannot mock the DefaultThreadFactory as the underlying
-        // PooledExecutor of the DefaultThreadPool will again wrapp it into a
-        // PooledExecutor.Worker instance that does some bookeeping.
-        // Using a easymocked DefaultThreadFactory will prevent the
-        // PooledExecutor from shutting down and thus hangs forever.
-        final ThreadFactory threadFactory = new DefaultThreadFactory();
-        threadFactory.setPriority( Thread.MAX_PRIORITY );
-        pool.setThreadFactory( threadFactory );
-        pool.setQueue( 230 );
-        pool.setMaximumPoolSize( 15 );
-        pool.setMinimumPoolSize( 9 );
-        pool.setKeepAliveTime( 11000 );
-        pool.setBlockPolicy( "ABORT" );
-        pool.setShutdownGraceful( false );
-        pool.setShutdownWaitTimeMs( 12345 );
-
-        assertEquals( "block-policy", "ABORT", pool.getBlockPolicy(  ) );
-        assertEquals( "keep-alive-time-ms", 11000L, pool.getKeepAliveTime(  ) );
-        assertEquals( "max-queueu-size", 230, pool.getMaximumQueueSize(  ) );
-        assertEquals( "max-pool-size", 15, pool.getMaximumPoolSize(  ) );
-        assertEquals( "min-pool-size", 9, pool.getMinimumPoolSize(  ) );
-        assertEquals( "name", "mypool", pool.getName(  ) );
-        assertEquals( "priority", Thread.MAX_PRIORITY, pool.getPriority(  ) );
-        assertEquals( "queue-size", 0, pool.getQueueSize(  ) );
-        assertEquals( "isQueued", true, pool.isQueued(  ) );
-        assertEquals( "isTerminatedAfterShutdown", false,
-                      pool.isTerminatedAfterShutdown(  ) );
-        verify(  );
+         * DOCUMENT ME!
+         */
+    public final void testDefaultThreadPool() {
+	final DefaultThreadPool pool = new DefaultThreadPool();
+	pool.setName("mypool");
+
+	// We cannot mock the DefaultThreadFactory as the underlying
+	// PooledExecutor of the DefaultThreadPool will again wrapp it into a
+	// PooledExecutor.Worker instance that does some bookeeping.
+	// Using a easymocked DefaultThreadFactory will prevent the
+	// PooledExecutor from shutting down and thus hangs forever.
+	final ThreadFactory threadFactory = new DefaultThreadFactory();
+	pool.setThreadFactory(threadFactory);
+	pool.setPriority(Thread.MAX_PRIORITY);
+	pool.setQueueSize(230);
+	pool.setMaxPoolSize(15);
+	pool.setMinPoolSize(9);
+	pool.setKeepAliveTime(11000L);
+	pool.setBlockPolicy("ABORT");
+	pool.setShutdownGraceful(false);
+	pool.setShutdownWaitTimeMs(12345);
+	pool.afterPropertiesSet();
+
+	assertEquals("block-policy", "ABORT", pool.getBlockPolicy());
+	assertEquals("keep-alive-time-ms", 11000L, pool.getKeepAliveTime());
+	assertEquals("max-queueu-size", 230, pool.getMaxQueueSize());
+	assertEquals("max-pool-size", 15, pool.getMaxPoolSize());
+	assertEquals("min-pool-size", 9, pool.getMinPoolSize());
+	assertEquals("name", "mypool", pool.getName());
+	assertEquals("priority", Thread.MAX_PRIORITY, pool.getPriority());
+	assertEquals("queue-size", 0, pool.getQueueSize());
+	assertEquals("isQueued", true, pool.isQueued());
+	assertEquals("isTerminatedAfterShutdown", false, pool
+		.isTerminatedAfterShutdown());
+	verify();
     }
 
     /*
-     * Class under test for void execute(Runnable)
-     */
-    public final void testExecuteRunnable(  )
-        throws InterruptedException
-    {
-        final MockControl runnableControl =
-            createStrictControl( Runnable.class );
-        final Runnable runnable = (Runnable)runnableControl.getMock(  );
-        runnable.run(  );
-        runnableControl.replay(  );
-
-        final DefaultThreadPool pool = new DefaultThreadPool(  );
-        pool.setName( "mypool" );
-        // We cannot mock the DefaultThreadFactory as the underlying
-        // PooledExecutor of the DefaultThreadPool will again wrapp it into a
-        // PooledExecutor.Worker instance that does some bookeeping.
-        // Using a easymocked DefaultThreadFactory will prevent the
-        // PooledExecutor from shutting down and thus hangs forever.
-        pool.setThreadFactory( new DefaultThreadFactory() );
-        pool.setQueue( 230 );
-        pool.setMaximumPoolSize( 15 );
-        pool.setMinimumPoolSize( 9 );
-        pool.setKeepAliveTime( 100 );
-        pool.setBlockPolicy( "ABORT" );
-        pool.setShutdownGraceful( false );
-        pool.setShutdownWaitTimeMs( 1234 );
-        pool.execute( runnable );
-        Thread.yield(  );
-        Thread.sleep( 100 );
-        pool.shutdown();
-        verify(  );
+         * Class under test for void execute(Runnable)
+         */
+    public final void testExecuteRunnable() throws InterruptedException {
+	final MockControl runnableControl = createStrictControl(Runnable.class);
+	final Runnable runnable = (Runnable) runnableControl.getMock();
+	runnable.run();
+	runnableControl.replay();
+
+	final DefaultThreadPool pool = new DefaultThreadPool();
+	pool.setName("mypool");
+	// We cannot mock the DefaultThreadFactory as the underlying
+	// PooledExecutor of the DefaultThreadPool will again wrapp it into a
+	// PooledExecutor.Worker instance that does some bookeeping.
+	// Using a easymocked DefaultThreadFactory will prevent the
+	// PooledExecutor from shutting down and thus hangs forever.
+	pool.setThreadFactory(new DefaultThreadFactory());
+	pool.setQueueSize(230);
+	pool.setMaxPoolSize(15);
+	pool.setMinPoolSize(9);
+	pool.setKeepAliveTime(100);
+	pool.setBlockPolicy("ABORT");
+	pool.setShutdownGraceful(false);
+	pool.setShutdownWaitTimeMs(1234);
+	pool.afterPropertiesSet();
+	pool.execute(runnable);
+	Thread.yield();
+	Thread.sleep(100);
+	pool.shutdown();
+	verify();
     }
 
     /**
-     * DOCUMENT ME!
-     *
-     * @throws InterruptedException DOCUMENT ME!
-     */
-    public final void testShutdown(  )
-    throws InterruptedException {
-        final Runnable runnable = new Runnable(){
-            public void run() {
-                final Log logger = LogFactory.getLog(DefaultThreadPoolTestCase.this.getClass());
-                logger.info( "runnable runs" );
-                try {
-                    Thread.sleep( 1000 );
-                } catch( final InterruptedException ie ) {
-                    logger.info( "runnable has been interrupted ");
-                }
-                logger.info( "runnable terminated" );
-            }
-        };
-
-        final DefaultThreadPool pool = new DefaultThreadPool(  );
-        pool.setName( "mypool" );
-        pool.setThreadFactory( new DefaultThreadFactory() );
-        pool.setQueue( 0 );
-        pool.setMaximumPoolSize( 15 );
-        pool.setMinimumPoolSize( 9 );
-        pool.setKeepAliveTime( 1000 );
-        pool.setBlockPolicy( "ABORT" );
-        pool.setShutdownGraceful( true );
-        pool.setShutdownWaitTimeMs( 100 );
-        pool.execute( runnable );
-        pool.execute( runnable );
-        Thread.yield();
-        Thread.sleep( 200 );
-        pool.shutdown(  );
-        Thread.sleep( 200 );
-        verify();
+         * DOCUMENT ME!
+         * 
+         * @throws InterruptedException
+         *                 DOCUMENT ME!
+         */
+    public final void testShutdown() throws InterruptedException {
+	final Runnable runnable = new Runnable() {
+	    public void run() {
+		final Log logger = LogFactory
+			.getLog(DefaultThreadPoolTestCase.this.getClass());
+		logger.info("runnable runs");
+		try {
+		    Thread.sleep(1000);
+		} catch (final InterruptedException ie) {
+		    logger.info("runnable has been interrupted ");
+		}
+		logger.info("runnable terminated");
+	    }
+	};
+
+	final DefaultThreadPool pool = new DefaultThreadPool();
+	pool.setName("mypool");
+	pool.setThreadFactory(new DefaultThreadFactory());
+	pool.setQueueSize(0);
+	pool.setMaxPoolSize(15);
+	pool.setMinPoolSize(9);
+	pool.setKeepAliveTime(1000);
+	pool.setBlockPolicy("ABORT");
+	pool.setShutdownGraceful(true);
+	pool.setShutdownWaitTimeMs(100);
+	pool.afterPropertiesSet();
+	pool.execute(runnable);
+	pool.execute(runnable);
+	Thread.yield();
+	Thread.sleep(200);
+	pool.shutdown();
+	Thread.sleep(200);
+	verify();
     }
 }