Package org.apache.excalibur.event.command

Source Code of org.apache.excalibur.event.command.TPCThreadManager

/*
* Copyright 1999-2004 The Apache Software Foundation
* Licensed  under the  Apache License,  Version 2.0  (the "License");
* you may not use  this file  except in  compliance with the License.
* You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed  under the  License is distributed on an "AS IS" BASIS,
* WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
* implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.excalibur.event.command;

import org.apache.avalon.framework.logger.NullLogger;
import org.apache.avalon.framework.parameters.ParameterException;
import org.apache.avalon.framework.parameters.Parameterizable;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.excalibur.util.SystemUtil;

import EDU.oswego.cs.dl.util.concurrent.PooledExecutor;
import EDU.oswego.cs.dl.util.concurrent.ThreadFactory;

/**
* This is a ThreadManager that uses a certain number of threads per
* processor.  The number of threads in the pool is a direct proportion to
* the number of processors. The size of the thread pool is (processors
* threads-per-processor) + 1
*
* @author <a href="mailto:dev@avalon.apache.org">Avalon Development Team</a>
*/
public final class TPCThreadManager extends AbstractThreadManager implements Parameterizable
{
    private PooledExecutor m_threadPool;
    private int m_processors = -1;
    private int m_threadsPerProcessor = 1;
    private int m_keepAliveTime = 300000;
    private boolean m_hardShutdown = false;

    /**
     * The following parameters can be set for this class:
     *
     * <table>
     *   <tr>
     *     <th>Name</th> <th>Description</th> <th>Default Value</th>
     *   </tr>
     *   <tr>
     *     <td>processors</td>
     *     <td>Number of processors (autodetected if less than one)</td>
     *     <td>Results from SystemUtil.numProcessors()</td>
     *   </tr>
     *   <tr>
     *     <td>threads-per-processor</td>
     *     <td>Threads per processor to use (Rewritten to 1 if less than one)</td>
     *     <td>1</td>
     *   </tr>
     *   <tr>
     *     <td>sleep-time</td>
     *     <td>Time (in milliseconds) to wait between queue pipeline processing runs</td>
     *     <td>1000</td>
     *   </tr>
     *   <tr>
     *     <td>keep-alive-time</td>
     *     <td>Time (in milliseconds) that idle threads should remain in the threadpool</td>
     *     <td>300000</td>
     *   </tr>
     *   <tr>
     *     <td>force-shutdown</td>
     *     <td>At shutdown time, allow currently queued tasks to finish, or immediately quit</td>
     *     <td>false</td>
     *   </tr>
     * </table>
     *
     * @param parameters  The Parameters object
     *
     * @throws ParameterException if there is a problem with the parameters.
     */
    public void parameterize( Parameters parameters ) throws ParameterException
    {
        m_processors = Math.max(1, parameters.getParameterAsInteger( "processors", 1 ) );

        m_threadsPerProcessor =
            Math.max( parameters.getParameterAsInteger( "threads-per-processor", 1 ), 1 );

        m_keepAliveTime = parameters.getParameterAsInteger("keep-alive-time", 300000);

        setSleepTime( parameters.getParameterAsLong( "sleep-time", 1000L ) );

        m_hardShutdown = ( parameters.getParameterAsBoolean( "force-shutdown", false ) );
    }

    public void initialize() throws Exception
    {
        if( m_processors < 1 )
        {
            m_processors = Math.max( 1, SystemUtil.numProcessors() );
        }

        if( isInitialized() )
        {
            throw new IllegalStateException( "ThreadManager is already initailized" );
        }

        final int maxPoolSize = Math.max(( m_processors * m_threadsPerProcessor ) + 1, m_processors + 1);
        m_threadPool = new PooledExecutor( m_processors + 1 );
        m_threadPool.setMinimumPoolSize( 2 ); // at least two threads
        m_threadPool.setMaximumPoolSize( maxPoolSize );
        m_threadPool.waitWhenBlocked();
        m_threadPool.setThreadFactory( new ThreadFactory() {
            public Thread newThread(Runnable run) {
                Thread newThread = new Thread(run);

                newThread.setDaemon( true );
                newThread.setPriority( Thread.MIN_PRIORITY );

                return newThread;
            }
        });
        if( maxPoolSize == 2 )
        {
            // The PooledExecutor has an inherent race condition between releasing threads
            // and adding new tasks (when using the waitWhenBlocked policy):
            // it could be that a thread is being released while a new
            // task is being added. That task would then remain waiting to be picked up by
            // the next thread that becomes available, but meanwhile the threadpool is below its maximum capacity.
            // If the threadpool has a maximum size of 1, then this could leave the task waiting forever.
            // Here we check if maxPoolSize == 2 because one of the threads used by the threadpool will
            // be used continuously by the ThreadManager itself.
            // As a solution to this problem, the one available work-thread we have in this case
            // is set to never expire.
            m_threadPool.setKeepAliveTime( -1 );
        }
        else
        {
            m_threadPool.setKeepAliveTime( m_keepAliveTime );
        }

        if( null == getLogger() )
        {
            this.enableLogging( new NullLogger() );
        }

        setExecutor( m_threadPool );

        super.initialize();
    }

    protected final void doDispose()
    {
        if ( m_hardShutdown )
        {
            m_threadPool.shutdownNow();
        }
        else
        {
            m_threadPool.shutdownAfterProcessingCurrentlyQueuedTasks();
        }

        m_threadPool.interruptAll();

        try
        {
            if ( !m_threadPool.awaitTerminationAfterShutdown( getSleepTime() ) )
            {
                getLogger().warn("Thread pool took longer than " + getSleepTime() +
                     " ms to shut down");
            }
        }
        catch (InterruptedException ie)
        {
            getLogger().warn("Thread pool was interrupted while waiting for shutdown to complete.", ie);
        }
    }
}
TOP

Related Classes of org.apache.excalibur.event.command.TPCThreadManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.