001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.web;
023:
024: import java.util.Stack;
025:
026: /**
027: * A simple thread pool.
028: *
029: * <a href="mailto:rickard.oberg@telkel.com">Rickard Öberg</a>
030: * @version $Revision: 57209 $
031: */
032: public class ThreadPool {
033: // Constants -----------------------------------------------------
034:
035: // Attributes ----------------------------------------------------
036:
037: /**
038: * Stack of idle threads cached for future use.
039: */
040: private final Stack pool = new Stack();
041:
042: /**
043: * Maximum number of idle threads cached in this pool.
044: */
045: private int maxSize = 10;
046:
047: private boolean enabled = false;
048:
049: // Static --------------------------------------------------------
050:
051: // Constructors --------------------------------------------------
052:
053: /**
054: * Create a new pool.
055: */
056: public ThreadPool() {
057: }
058:
059: // Public --------------------------------------------------------
060: public synchronized void enable() {
061: enabled = true;
062: }
063:
064: public synchronized void disable() {
065: enabled = false;
066: while (!pool.isEmpty()) {
067: Worker w = (Worker) pool.pop();
068: w.die();
069: } // end of while ()
070: }
071:
072: /**
073: * Set the maximum number of idle threads cached in this pool.
074: */
075: public void setMaximumSize(int size) {
076: maxSize = size;
077: }
078:
079: /**
080: * Do some work.
081: * This will either create a new thread to do the work, or
082: * use an existing idle cached thread.
083: */
084: public synchronized void run(Runnable work) {
085: if (pool.size() == 0) {
086: new Worker(work);
087: } else {
088: Worker w = (Worker) pool.pop();
089: w.run(work);
090: }
091: }
092:
093: // Private -------------------------------------------------------
094:
095: /**
096: * Return an idle worker thread to the pool of cached idle threads.
097: * This is called from the worker thread itself.
098: */
099: private synchronized void returnWorker(Worker w) {
100: if (enabled && pool.size() < maxSize) {
101: pool.push(w);
102: } else {
103: w.die();
104: } // end of else
105: }
106:
107: // Inner classes -------------------------------------------------
108:
109: class Worker extends Thread {
110: /**
111: * Flags that this worker may continue to work.
112: */
113: boolean running = true;
114:
115: /**
116: * Work to do, of <code>null</code> if no work to do.
117: */
118: Runnable work;
119:
120: /**
121: * Create a new Worker to do some work.
122: */
123: Worker(Runnable work) {
124: this .work = work;
125: setDaemon(true);
126: start();
127: }
128:
129: /**
130: * Tell this worker to die.
131: */
132: public synchronized void die() {
133: running = false;
134: this .notify();
135: }
136:
137: /**
138: * Give this Worker some work to do.
139: *
140: * @throws IllegalStateException If this worker already
141: * has work to do.
142: */
143: public synchronized void run(Runnable work) {
144: if (this .work != null)
145: throw new IllegalStateException(
146: "Worker already has work to do.");
147: this .work = work;
148: this .notify();
149: }
150:
151: /**
152: * The worker loop.
153: */
154: public void run() {
155: while (running) {
156: // If work is available then execute it
157: if (work != null) {
158: try {
159: work.run();
160: } catch (Exception e) {
161: //DEBUG Logger.exception(e);
162: }
163: // Clear work
164: work = null;
165: }
166:
167: // Return to pool of cached idle threads
168: returnWorker(this );
169:
170: // Wait for more work to become available
171: synchronized (this ) {
172: while (running && work == null) {
173: try {
174: this .wait();
175: } catch (InterruptedException e) {
176: // Ignore
177: }
178: }
179: }
180: }
181: }
182:
183: }
184: }
|