Package org.apache.sling.commons.threads.impl

Source Code of org.apache.sling.commons.threads.impl.DefaultThreadPool

/*
* 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.
*/
package org.apache.sling.commons.threads.impl;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.apache.sling.commons.threads.ModifiableThreadPoolConfig;
import org.apache.sling.commons.threads.ThreadPool;
import org.apache.sling.commons.threads.ThreadPoolConfig;
import org.apache.sling.commons.threads.ThreadPoolManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
* The DefaultThreadPool class implements the {@link ThreadPool} interface.
* Instances of this class are managed by the {@link ThreadPoolManager}.
*/
public class DefaultThreadPool
    implements ThreadPool {

    /** By default we use the logger for this class. */
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    /** The name of this thread pool */
    protected final String name;

    /** The executor. */
    protected ThreadPoolExecutor executor;

    protected final ModifiableThreadPoolConfig configuration;

    /**
     * Create a new thread pool.
     * @param name - The name of the thread pool. If null {@link DefaultThreadPoolManager#DEFAULT_THREADPOOL_NAME}
     *               is used
     */
    public DefaultThreadPool(final String name,
                             final ThreadPoolConfig origConfig) {
        // name
        if ( name != null ) {
            this.name = name;
        } else {
            this.name = DefaultThreadPoolManager.DEFAULT_THREADPOOL_NAME;
        }

        this.logger.info("Initializing thread pool [{}]  ...", this.name);

        this.configuration = new ModifiableThreadPoolConfig(origConfig);

        // factory
        final ThreadFactory delegateThreadFactory;
        if (this.configuration.getFactory() == null) {
            logger.debug("Thread pool [{}] ; No ThreadFactory is configured. Will use JVM default thread factory: {}",
                    this.name, ExtendedThreadFactory.class.getName());
            delegateThreadFactory = Executors.defaultThreadFactory();
        } else {
            delegateThreadFactory = this.configuration.getFactory();
        }
        // Min pool size
        if (this.configuration.getMinPoolSize() < 1) {
            this.configuration.setMinPoolSize(1);
            this.logger.warn("min-pool-size < 1 for pool \"" + this.name + "\". Set to 1");
        }
        // Max pool size
        if ( this.configuration.getMaxPoolSize() < 0 ) {
            this.configuration.setMaxPoolSize(Integer.MAX_VALUE);
        }

        // Set priority and daemon flag
        final ExtendedThreadFactory threadFactory = new ExtendedThreadFactory(delegateThreadFactory, this.configuration.getPriority(), this.configuration.isDaemon());

        // Keep alive time
        if (this.configuration.getKeepAliveTime() < 0) {
            this.configuration.setKeepAliveTime(1000);
            this.logger.warn("keep-alive-time-ms < 0 for pool \"" + this.name + "\". Set to 1000");
        }

        // Queue
        final BlockingQueue<Runnable> queue;
        if (this.configuration.getQueueSize() != 0) {
            if (this.configuration.getQueueSize() > 0) {
                queue = new java.util.concurrent.ArrayBlockingQueue<Runnable>(this.configuration.getQueueSize());
            } else {
                queue = new LinkedBlockingQueue<Runnable>();
            }
        } else {
            queue = new SynchronousQueue<Runnable>();
        }

        RejectedExecutionHandler handler = null;
        switch (this.configuration.getBlockPolicy()) {
            case ABORT :
                handler = new ThreadPoolExecutor.AbortPolicy();
                break;
            case DISCARD :
                handler = new ThreadPoolExecutor.DiscardPolicy();
                break;
            case DISCARDOLDEST :
                handler = new ThreadPoolExecutor.DiscardOldestPolicy();
                break;
            case RUN :
                handler = new ThreadPoolExecutor.CallerRunsPolicy();
                break;
        }
        this.executor = new ThreadPoolExecutor(this.configuration.getMinPoolSize(),
                this.configuration.getMaxPoolSize(),
                this.configuration.getKeepAliveTime(),
                TimeUnit.MILLISECONDS,
                queue,
                threadFactory,
                handler);
        this.logger.info("Thread pool [{}] initialized.", name);
    }

    /**
     * @see org.apache.sling.commons.threads.ThreadPool#getName()
     */
    public String getName() {
      return name;
    }


    /**
     * @see org.apache.sling.commons.threads.ThreadPool#getConfiguration()
     */
    public ThreadPoolConfig getConfiguration() {
        return this.configuration;
    }

    /**
     * @see org.apache.sling.commons.threads.ThreadPool#execute(java.lang.Runnable)
     */
    public void execute(final Runnable runnable) {
        checkExecutor();
        if ( runnable != null ) {
            if ( logger.isDebugEnabled() ) {
                logOperation("Executing runnable: ", runnable);
            }
            executor.execute(runnable);
        }
    }

    /**
     * @see org.apache.sling.commons.threads.ThreadPool#submit(java.util.concurrent.Callable)
     */
    public <T> Future<T> submit(final Callable<T> callable) {
        checkExecutor();
        if ( logger.isDebugEnabled() ) {
            logOperation("Submitting callable: ", callable);
        }
        return executor.submit(callable);
    }

    /**
     * @see org.apache.sling.commons.threads.ThreadPool#submit(java.lang.Runnable)
     */
    public Future<?> submit(final Runnable runnable) {
        checkExecutor();
        if ( logger.isDebugEnabled() ) {
            logOperation("Submitting runnable: ", runnable);
        }
        return executor.submit(runnable);
    }

    /**
     * Shut down the threadpool.
     */
    public void shutdown() {
        this.logger.info("Shutting down thread pool [{}] ...", name);
        if ( this.executor != null ) {
            if (this.configuration.isShutdownGraceful()) {
                this.executor.shutdown();
            } else {
                this.executor.shutdownNow();
            }

            try {
                if (this.configuration.getShutdownWaitTimeMs() > 0) {
                    if (!this.executor.awaitTermination(this.configuration.getShutdownWaitTimeMs(), TimeUnit.MILLISECONDS)) {
                        logger.warn("Running commands have not terminated within "
                            + this.configuration.getShutdownWaitTimeMs()
                            + "ms. Will shut them down by interruption");
                        this.executor.shutdownNow();
                    }
                }
            } catch (final InterruptedException ie) {
                this.logger.error("Cannot shutdown thread pool [" + this.name + "]", ie);
            }
            this.executor = null;
        }
        this.logger.info("Thread pool [{}] is shut down.", this.name);
    }

    public ThreadPoolExecutor getExecutor() {
        return this.executor;
    }

    private void checkExecutor() {
        if ( this.executor == null ) {
            throw new IllegalStateException("Thread pool " + this.name + " is already shutdown.");
        }
    }

    private void logOperation(final String msg, final Object obj) {
        logger.debug("{} {}, pool={}, active={}, corePoolSize={}, maxPoolSize={}, queueSize={}",
                new Object[] {msg, obj, name,
                        executor.getActiveCount(),
                        executor.getCorePoolSize(),
                        executor.getMaximumPoolSize(),
                        executor.getQueue().size()});
    }
}
TOP

Related Classes of org.apache.sling.commons.threads.impl.DefaultThreadPool

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.