| ThreadPool.java |
/*
* JBoss, the OpenSource J2EE webOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.mx.util;
import java.util.Stack;
/**
* A simple thread pool. Idle threads are cached for future use.
* The cache grows until it reaches a maximum size (default 10).
* When there is nothing in the cache, a new thread is created.
* By default the threads are daemon threads.
*
* <a href="mailto:rickard.oberg@telkel.com">Rickard …berg</a>
* <a href="mailto:adrian.brock@happeningtimes.com">Adrian Brock</a>
* @version $Revision: 1.6 $
*/
public class ThreadPool
{
// Constants -----------------------------------------------------
// Attributes ----------------------------------------------------
private static int counter = 0;
/**
* Stack of idle threads cached for future use.
*/
private Stack pool = new Stack();
/**
* Maximum number of idle threads cached in this pool.
*/
private int maxSize = 10;
/**
* Is the thread pool active
*/
private boolean active = false;
/**
* Whether the threads are daemon threads.
*/
private boolean daemon = true;
// Static --------------------------------------------------------
// Constructors --------------------------------------------------
/**
* Create a new pool.
*/
public ThreadPool()
{
}
/**
* Create a new pool with an activity status
*
* @param active true for active, false otherwise
*/
public ThreadPool(boolean active)
{
this.active = active;
}
// Public --------------------------------------------------------
/**
* Set the maximum number of idle threads cached in this pool.
*
* @param size the new maximum size.
*/
public void setMaximumSize(int size)
{
maxSize = size;
}
/**
* Get the maximum number of idle threads cached in this pool.
*
* @return the maximum size
*/
public int getMaximumSize()
{
return maxSize;
}
/**
* Set the activity status of the pool. Setting the pool to
* inactive, clears the pool.
*
* @param status pass true for active, false otherwise.
*/
public void setActive(boolean status)
{
active = status;
if (active == false)
while (pool.size() > 0)
((Worker)pool.pop()).die();
}
/**
* Get the activity status of the pool.
*
* @return true for an active pool, false otherwise.
*/
public boolean isActive()
{
return active;
}
/**
* Set whether new threads are daemon threads.
*
* @param value pass true for daemon threads, false otherwise.
*/
public void setDaemonThreads(boolean value)
{
daemon = value;
}
/**
* Get whether new threads are daemon threads.
*
* @return true for daemon threads, false otherwise.
*/
public boolean getDaemonThreads()
{
return daemon;
}
/**
* Do some work.
* This will either create a new thread to do the work, or
* use an existing idle cached thread.
*
* @param work the work to perform.
*/
public synchronized void run(Runnable work)
{
if (pool.size() == 0)
new Worker(work);
else
{
Worker worker = (Worker) pool.pop();
worker.run(work);
}
}
// Private -------------------------------------------------------
/**
* Put an idle worker thread back in the pool of cached idle threads.
* This is called from the worker thread itself. When the cache is
* full, the thread is discarded.
*
* @param worker the worker to return.
*/
private synchronized void returnWorker(Worker worker)
{
if (pool.size() < maxSize)
pool.push(worker);
else
worker.die();
}
// Inner classes -------------------------------------------------
/**
* A worker thread runs a worker.
*/
class Worker extends Thread
{
/**
* Flags that this worker may continue to work.
*/
boolean running = true;
/**
* Work to do, of <code>null</code> if no work to do.
*/
Runnable work;
/**
* Create a new Worker to do some work.
*
* @param work the work to perform
*/
Worker(Runnable work)
{
// give it a thread so we can figure out what this thread is in debugging
super("ThreadPoolWorker["+(++counter)+"]");
this.work = work;
setDaemon(daemon);
start();
}
/**
* Tell this worker to die.
*/
public synchronized void die()
{
running = false;
this.notify();
}
/**
* Give this Worker some work to do.
*
* @param the work to perform.
* @throws IllegalStateException If this worker already
* has work to do.
*/
public synchronized void run(Runnable work)
{
if (this.work != null)
throw new IllegalStateException("Worker already has work to do.");
this.work = work;
this.notify();
}
/**
* The worker loop.
*/
public void run()
{
while (active && running)
{
// If work is available then execute it
if (work != null)
{
try
{
work.run();
}
catch (Exception ignored) {}
// Clear work
work = null;
}
// Return to pool of cached idle threads
returnWorker(this);
// Wait for more work to become available
synchronized (this)
{
while (running && work == null)
{
try
{
this.wait();
}
catch (InterruptedException ignored) {}
}
}
}
}
}
}
| ThreadPool.java |