⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 threadpool.java

📁 一个java方面的消息订阅发送的源码
💻 JAVA
字号:
/**
 * Redistribution and use of this software and associated documentation
 * ("Software"), with or without modification, are permitted provided
 * that the following conditions are met:
 *
 * 1. Redistributions of source code must retain copyright
 *    statements and notices.  Redistributions must also contain a
 *    copy of this document.
 *
 * 2. Redistributions in binary form must reproduce the
 *    above copyright notice, this list of conditions and the
 *    following disclaimer in the documentation and/or other
 *    materials provided with the distribution.
 *
 * 3. The name "Exolab" must not be used to endorse or promote
 *    products derived from this Software without prior written
 *    permission of Exoffice Technologies.  For written permission,
 *    please contact info@exolab.org.
 *
 * 4. Products derived from this Software may not be called "Exolab"
 *    nor may "Exolab" appear in their names without prior written
 *    permission of Exoffice Technologies. Exolab is a registered
 *    trademark of Exoffice Technologies.
 *
 * 5. Due credit should be given to the Exolab Project
 *    (http://www.exolab.org/).
 *
 * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
 * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Copyright 2000-2004 (C) Exoffice Technologies Inc. All Rights Reserved.
 *
 * $Id: ThreadPool.java,v 1.1 2004/11/26 01:50:35 tanderson Exp $
 */
package org.exolab.jms.common.threads;

import org.exolab.jms.common.util.FifoQueue;


/**
 * Thread manager that maintains a list of worker threads and allocates
 * them to execute objects asynchronously. This enables execution without the
 * overhead of thread creation.
 * <p>
 * The thread pool is constructed with a fixed number of threads.
 * The number of threads cannot be increased after the pool is created, but
 * there can be multiple thread pools.
 * <p>
 * There are two methods to execute threads:
 * <ul>
 *   <li>{@link #execute} - this executes an {@link Runnable} object using
 *       the first available worker thread. If no threads are available,
 *       the call blocks until one is free.</li>
 *   <li>{@link #queue} - this queues an {@link Runnable} object for later
 *       execution by the first available worker thread. It returns immediately
 *       without blocking.</li>
 * </ul>
 *
 * @version     $Revision: 1.1 $ $Date: 2004/11/26 01:50:35 $
 * @author      <a href="mailto:mourikis@exolab.org">Jim Mourikis</a>
 * @see         CompletionListener
 */
public class ThreadPool {

    /**
     * The name of this thread pool
     */
    private final String _name;

    /**
     * The thread group of this pool
     */
    private ThreadGroup _group;

    /**
     * The list of idle threads ready for use
     */
    private FifoQueue _idleWorkers;

    /**
     * The list of all worker threads, working or idle
     */
    private ThreadPoolWorker[] _workers;

    /**
     * The queue of pending {@link Runnable} instances
     */
    private QueueWorker _queue;

    /**
     * Seed value for creating unique thread pool names
     */
    private static volatile int _poolSeed = 0;


    /**
     * Create a new thread pool with the requested number of threads.
     * Each thread will be allocated to a new ThreadGroup named
     * 'ThreadPool-'<id> where id is a number incremented for each new thread
     * pool.
     *
     * @param threads the number of threads to allocate to the pool
     * @throws IllegalArgumentException if the number of threads is less than 1
     */
    public ThreadPool(int threads) {
        this(threads, false);
    }

    /**
     * Create a new thread pool with the requested number of threads.
     * Each thread will be allocated to a new ThreadGroup named
     * 'ThreadPool-'<id> where id is a number incremented for each new thread
     * pool.
     *
     * @param threads the number of threads to allocate to the pool
     * @param daemon if <code>true</code> all threads will be daemon threads
     * @throws IllegalArgumentException if the number of threads is less than 1
     */
    public ThreadPool(int threads, boolean daemon) {
        this("ThreadPool-" +  ++_poolSeed, threads, daemon);
    }

    /**
     * Create a new thread pool with the requested number of threads.
     * Each thread will be allocated to a new ThreadGroup with the specified
     * name.
     *
     * @param name the name of the thread group
     * @param threads the number of threads to allocate to the pool
     * @throws IllegalArgumentException if the number of threads is less than 1
     */
    public ThreadPool(String name, int threads) {
        this(name, threads, false);
    }

    /**
     * Create a new thread pool with the requested number of threads.
     * Each thread will be allocated to a new ThreadGroup with the specified
     * name.
     *
     * @param name the name of the thread group
     * @param threads the number of threads to allocate to the pool
     * @param daemon if <code>true</code> all threads will be daemon threads
     * @throws IllegalArgumentException if the number of threads is less than 1
     */
    public ThreadPool(String name, int threads, boolean daemon) {
        this(new ThreadGroup(name), threads, daemon);
    }

    /**
     * Create a new thread pool with the requested number of threads.
     * Each thread will be associated with the supplied thread group.
     *
     * @param group the thread group
     * @param threads the number of threads to allocate to the pool
     * @param daemon if <code>true</code> all threads will be daemon threads
     * @throws IllegalArgumentException if the number of threads is less than 1
     */
    public ThreadPool(ThreadGroup group, int threads, boolean daemon) {
        _name = group.getName();
        _group = new ThreadGroup(_name);
        if (daemon) {
            _group.setDaemon(true);
        }
        if (threads < 1) {
            throw new IllegalArgumentException(
                "Argument 'threads' must be > 0");
        }

        _idleWorkers = new FifoQueue(threads);
        _workers = new ThreadPoolWorker[threads];

        for (int i = 0; i < _workers.length; ++i) {
            String id = _name + "-Worker-" + i;
            _workers[i] = new ThreadPoolWorker(_group, id, _idleWorkers);
        }
    }

    /**
     * Execute the {@link Runnable} object using the next available
     * worker thread. This method will block until a worker thread is
     * available for use - once a worker thread becomes available it
     * will return immediately.
     *
     * @param target the work to perform
     * @throws InterruptedException if this thread is interrupted externally
     */
    public void execute(Runnable target) throws InterruptedException {
        // block (forever) until a worker is available
        ThreadPoolWorker worker = (ThreadPoolWorker) _idleWorkers.get();
        worker.process(target);
    }

    /**
     * Queue the {@link Runnable} object for execution using the next
     * available worker thread.<br/>
     * Unlike {@link #execute}, this method does not block.
     *
     * @param target the work to perform
     */
    public void queue(Runnable target) {
        queue(target, null);
    }

    /**
     * Queue the {@link Runnable} object for execution using the next
     * available worker thread. When the object completes execution, the
     * completion listener will be notified.<br/>
     * Unlike {@link #execute}, this method does not block.
     *
     * @param target the work to perform
     * @param listener the listener to notify when the object has completed
     * executing
     */
    public synchronized void queue(Runnable target,
                                   CompletionListener listener) {
        if (_queue == null) {
            _queue = new QueueWorker(this, _group, _name + "-QueueWorker");
        }
        _queue.add(target, listener);
    }

    /**
     * Shuts down and removes any idle threads from the queue.
     * Working threads will not be shutdown.
     * As working threads finish, and are added back to the idle queue
     * this call needs to be made again to shut them down and remove them.
     */
    public void stopRequestIdleWorkers() {
        try {
            Object[] idle = _idleWorkers.getAll();
            for (int i = 0; i < idle.length; i++) {
                ((ThreadPoolWorker) idle[i]).stopRequest();
            }
        } catch (InterruptedException exception) {
            // re-assert
            Thread.currentThread().interrupt();
        }
    }

    /**
     * Shuts down and removes all threads.
     * First all idle threads are removed and shutdown,
     * then all remaining work threads, are shutdown.
     */
    public void stopRequestAllWorkers() {
        final long delay = 250;
        stopRequestIdleWorkers();

        // give the idle workers a quick chance to die
        try {
            Thread.sleep(delay);
        } catch (InterruptedException ignore) {
        }

        for (int i = 0; i < _workers.length; i++) {
            if (_workers[i].isAlive()) {
                _workers[i].stopRequest();
            }
        }

        if (_queue != null && _queue.isAlive()) {
            _queue.stop();
        }
    }

    /**
     * Determines if there is at least one idle thread.
     * This never blocks.
     *
     * @return <code>true</code> if there are one or more idle threads
     */
    boolean hasIdleThread() {
        return (_idleWorkers.isEmpty() ? false : true);
    }

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -