?? threadpool.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 + -