Package org.apache.jcs.utils.threadpool

Source Code of org.apache.jcs.utils.threadpool.ThreadPoolManager$MyThreadFactory

package org.apache.jcs.utils.threadpool;

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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.
*/

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jcs.utils.props.PropertyLoader;
import org.apache.jcs.utils.threadpool.behavior.IPoolConfiguration;

import EDU.oswego.cs.dl.util.concurrent.BoundedBuffer;
import EDU.oswego.cs.dl.util.concurrent.Channel;
import EDU.oswego.cs.dl.util.concurrent.LinkedQueue;
import EDU.oswego.cs.dl.util.concurrent.PooledExecutor;
import EDU.oswego.cs.dl.util.concurrent.ThreadFactory;

/**
* This manages threadpools for an application using Doug Lea's Util Concurrent
* package.
* http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html
* <p>
* It is a singleton since threads need to be managed vm wide.
* <p>
* This manager forces you to use a bounded queue. By default it uses the
* current thread for execuion when the buffer is full and no free threads can
* be created.
* <p>
* You can specify the props file to use or pass in a properties object prior to
* configuration. By default it looks for configuration information in
* thread_pool.properties.
* <p>
* If set, the Properties object will take precedence.
* <p>
* If a value is not set for a particular pool, the hard coded defaults will be
* used.
*
* <pre>
* int boundarySize_DEFAULT = 2000;
*
* int maximumPoolSize_DEFAULT = 150;
*
* int minimumPoolSize_DEFAULT = 4;
*
* int keepAliveTime_DEFAULT = 1000 * 60 * 5;
*
* boolean abortWhenBlocked = false;
*
* String whenBlockedPolicy_DEFAULT = IPoolConfiguration.POLICY_RUN;
*
* int startUpSize_DEFAULT = 4;
* </pre>
*
* You can configure default settings by specifying a default pool in the
* properties, ie "cache.ccf"
* <p>
* @author Aaron Smuts
*/
public class ThreadPoolManager
{
    private static final Log log = LogFactory.getLog( ThreadPoolManager.class );

    // DEFAULT SETTINGS, these are not final since they can be set
    // via the Propeties file or object
    private static boolean useBoundary_DEFAULT = true;

    private static int boundarySize_DEFAULT = 2000;

    private static int maximumPoolSize_DEFAULT = 150;

    private static int minimumPoolSize_DEFAULT = 4;

    private static int keepAliveTime_DEFAULT = 1000 * 60 * 5;

    private static String whenBlockedPolicy_DEFAULT = IPoolConfiguration.POLICY_RUN;

    private static int startUpSize_DEFAULT = 4;

    private static PoolConfiguration defaultConfig;

    // This is the default value. Setting this after
    // inialization will have no effect
    private static String propsFileName = "cache.ccf";

    // the root property name
    private static String PROP_NAME_ROOT = "thread_pool";

    private static String DEFAULT_PROP_NAME_ROOT = "thread_pool.default";

    // You can specify the properties to be used to configure
    // the thread pool. Setting this post initialization will have
    // no effect.
    private static Properties props = null;

    private static HashMap pools = new HashMap();

    // singleton instance
    private static ThreadPoolManager INSTANCE = null;

    /**
     * No instances please. This is a singleton.
     */
    private ThreadPoolManager()
    {
        configure();
    }

    /**
     * Creates a pool based on the configuration info.
     * <p>
     * @param config
     * @return A ThreadPoll wrapper
     */
    private ThreadPool createPool( PoolConfiguration config )
    {
        PooledExecutor pool = null;
        Channel queue = null;
        if ( config.isUseBoundary() )
        {
            if ( log.isDebugEnabled() )
            {
                log.debug( "Creating a Bounded Buffer to use for the pool" );
            }
            queue = new BoundedBuffer( config.getBoundarySize() );
            pool = new PooledExecutor( queue, config.getMaximumPoolSize() );
            pool.setThreadFactory( new MyThreadFactory() );
        }
        else
        {
            if ( log.isDebugEnabled() )
            {
                log.debug( "Creating a non bounded Linked Queue to use for the pool" );
            }
            queue = new LinkedQueue();
            pool = new PooledExecutor( queue, config.getMaximumPoolSize() );
        }

        pool.setMinimumPoolSize( config.getMinimumPoolSize() );
        pool.setKeepAliveTime( config.getKeepAliveTime() );

        // when blocked policy
        if ( config.getWhenBlockedPolicy().equals( IPoolConfiguration.POLICY_ABORT ) )
        {
            pool.abortWhenBlocked();
        }
        else if ( config.getWhenBlockedPolicy().equals( IPoolConfiguration.POLICY_RUN ) )
        {
            pool.runWhenBlocked();
        }
        else if ( config.getWhenBlockedPolicy().equals( IPoolConfiguration.POLICY_WAIT ) )
        {
            pool.waitWhenBlocked();
        }
        else if ( config.getWhenBlockedPolicy().equals( IPoolConfiguration.POLICY_ABORT ) )
        {
            pool.abortWhenBlocked();
        }
        else if ( config.getWhenBlockedPolicy().equals( IPoolConfiguration.POLICY_DISCARDOLDEST ) )
        {
            pool.discardOldestWhenBlocked();
        }

        pool.createThreads( config.getStartUpSize() );

        return new ThreadPool( pool, queue );
    }

    /**
     * Returns a configured instance of the ThreadPoolManger To specify a
     * configuation file or Properties object to use call the appropriate setter
     * prior to calling getInstance.
     * <p>
     * @return The single instance of the ThreadPoolManager
     */
    public static synchronized ThreadPoolManager getInstance()
    {
        if ( INSTANCE == null )
        {
            INSTANCE = new ThreadPoolManager();
        }
        return INSTANCE;
    }

    /**
     * Returns a pool by name. If a pool by this name does not exist in the
     * configuration file or properties, one will be created using the default
     * values.
     * <p>
     * Pools are lazily created.
     * <p>
     * @param name
     * @return The thread pool configured for the name.
     */
    public ThreadPool getPool( String name )
    {
        ThreadPool pool = null;

        synchronized ( pools )
        {
            pool = (ThreadPool) pools.get( name );
            if ( pool == null )
            {
                if ( log.isDebugEnabled() )
                {
                    log.debug( "Creating pool for name [" + name + "]" );
                }
                PoolConfiguration config = this.loadConfig( PROP_NAME_ROOT + "." + name );
                pool = createPool( config );

                if ( pool != null )
                {
                    pools.put( name, pool );
                }

                if ( log.isDebugEnabled() )
                {
                    log.debug( "PoolName = " + getPoolNames() );
                }
            }
        }

        return pool;
    }

    /**
     * Returns the names of all configured pools.
     * <p>
     * @return ArrayList of string names
     */
    public ArrayList getPoolNames()
    {
        ArrayList poolNames = new ArrayList();
        synchronized ( pools )
        {
            Set names = pools.keySet();
            Iterator it = names.iterator();
            while ( it.hasNext() )
            {
                poolNames.add( it.next() );
            }
        }
        return poolNames;
    }

    /**
     * Setting this post initialization will have no effect.
     * <p>
     * @param propsFileName
     *            The propsFileName to set.
     */
    public static void setPropsFileName( String propsFileName )
    {
        ThreadPoolManager.propsFileName = propsFileName;
    }

    /**
     * Returns the name of the properties file that we used to initialize the
     * pools. If the value was set post-initialization, then it may not be the
     * file used.
     * <p>
     * @return Returns the propsFileName.
     */
    public static String getPropsFileName()
    {
        return propsFileName;
    }

    /**
     * This will be used if it is not null on initialzation. Setting this post
     * initialization will have no effect.
     * <p>
     * @param props
     *            The props to set.
     */
    public static void setProps( Properties props )
    {
        ThreadPoolManager.props = props;
    }

    /**
     * @return Returns the props.
     */
    public static Properties getProps()
    {
        return props;
    }

    /**
     * Intialize the ThreadPoolManager and create all the pools defined in the
     * configuration.
     */
    protected void configure()
    {
        if ( log.isDebugEnabled() )
        {
            log.debug( "Initializing ThreadPoolManager" );
        }

        if ( props == null )
        {
            try
            {
                props = PropertyLoader.loadProperties( propsFileName );

                if ( log.isDebugEnabled() )
                {
                    log.debug( "File contained " + props.size() + " properties" );
                }
            }
            catch ( Exception e )
            {
                log.error( "Problem loading properties. propsFileName [" + propsFileName + "]", e );
            }
        }

        if ( props == null )
        {
            log.warn( "No configuration settings found.  Using hardcoded default values for all pools." );
            props = new Properties();
        }

        // set intial default and then override if new
        // settings are available
        defaultConfig = new PoolConfiguration( useBoundary_DEFAULT, boundarySize_DEFAULT, maximumPoolSize_DEFAULT,
                                               minimumPoolSize_DEFAULT, keepAliveTime_DEFAULT,
                                               whenBlockedPolicy_DEFAULT, startUpSize_DEFAULT );

        defaultConfig = loadConfig( DEFAULT_PROP_NAME_ROOT );
    }

    /**
     * Configures the default PoolConfiguration settings.
     * <p>
     * @param root
     * @return PoolConfiguration
     */
    protected PoolConfiguration loadConfig( String root )
    {
        PoolConfiguration config = (PoolConfiguration) defaultConfig.clone();

        if ( props.containsKey( root + ".useBoundary" ) )
        {
            try
            {
                config.setUseBoundary( Boolean.valueOf( (String) props.get( root + ".useBoundary" ) ).booleanValue() );
            }
            catch ( NumberFormatException nfe )
            {
                log.error( "useBoundary not a boolean.", nfe );
            }
        }

        // load default if they exist
        if ( props.containsKey( root + ".boundarySize" ) )
        {
            try
            {
                config.setBoundarySize( Integer.parseInt( (String) props.get( root + ".boundarySize" ) ) );
            }
            catch ( NumberFormatException nfe )
            {
                log.error( "boundarySize not a number.", nfe );
            }
        }

        // maximum pool size
        if ( props.containsKey( root + ".maximumPoolSize" ) )
        {
            try
            {
                config.setMaximumPoolSize( Integer.parseInt( (String) props.get( root + ".maximumPoolSize" ) ) );
            }
            catch ( NumberFormatException nfe )
            {
                log.error( "maximumPoolSize not a number.", nfe );
            }
        }

        // minimum pool size
        if ( props.containsKey( root + ".minimumPoolSize" ) )
        {
            try
            {
                config.setMinimumPoolSize( Integer.parseInt( (String) props.get( root + ".minimumPoolSize" ) ) );
            }
            catch ( NumberFormatException nfe )
            {
                log.error( "minimumPoolSize not a number.", nfe );
            }
        }

        // keep alive
        if ( props.containsKey( root + ".keepAliveTime" ) )
        {
            try
            {
                config.setKeepAliveTime( Integer.parseInt( (String) props.get( root + ".keepAliveTime" ) ) );
            }
            catch ( NumberFormatException nfe )
            {
                log.error( "keepAliveTime not a number.", nfe );
            }
        }

        // when blocked
        if ( props.containsKey( root + ".whenBlockedPolicy" ) )
        {
            config.setWhenBlockedPolicy( (String) props.get( root + ".whenBlockedPolicy" ) );
        }

        // startupsize
        if ( props.containsKey( root + ".startUpSize" ) )
        {
            try
            {
                config.setStartUpSize( Integer.parseInt( (String) props.get( root + ".startUpSize" ) ) );
            }
            catch ( NumberFormatException nfe )
            {
                log.error( "startUpSize not a number.", nfe );
            }
        }

        if ( log.isInfoEnabled() )
        {
            log.info( root + " PoolConfiguration = " + config );
        }

        return config;
    }

    /**
     * Allows us to set the daemon status on the threads.
     * <p>
     * @author aaronsm
     */
    class MyThreadFactory
        implements ThreadFactory
    {
        /*
         * (non-Javadoc)
         *
         * @see EDU.oswego.cs.dl.util.concurrent.ThreadFactory#newThread(java.lang.Runnable)
         */
        public Thread newThread( Runnable runner )
        {
            Thread t = new Thread( runner );
            t.setDaemon( true );
            return t;
        }
    }
}
TOP

Related Classes of org.apache.jcs.utils.threadpool.ThreadPoolManager$MyThreadFactory

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.