/** * Copyright (c) 1996,1997,1998 Sun Microsystems, Inc. All Rights Reserved. * * Permission to use, copy, modify, and distribute this software * and its documentation for NON-COMMERCIAL purposes and without * fee is hereby granted provided that this copyright notice * appears in all copies. Please refer to the file "copyright.html" * for further important copyright and licensing information. * * The Java source code is the confidential and proprietary information * of Sun Microsystems, Inc. ("Confidential Information"). You shall * not disclose such Confidential Information and shall use it only in * accordance with the terms of the license agreement you entered into * with Sun. * * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. */ import java.util.*; /** * Implements Thread Pooling. Thread Pool simply keeps a * bunch of suspended threads around to do some work. */ public class Pool { /** * Handler class for perform work * requested by the Pool. */ class WorkerThread extends Thread { private Worker _worker; private Object _data; /** * Creates a new WorkerThread * @param id Thread ID * @param worker Worker instance associated with the WorkerThread */ WorkerThread(String id, Worker worker) { super(id); _worker = worker; _data = null; } /** * Wakes the thread and does some work * @param data Data to send to the Worker * @return void */ synchronized void wake (Object data) { _data = data; notify(); } /** * WorkerThread's thread routine */ synchronized public void run() { boolean stop = false; while (!stop) { if ( _data == null ) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); continue; } } if ( _data != null ) { _worker.run(_data); } _data = null; stop = !(_push (this)); } } }; private Stack _waiting; private int _max; private Class _workerClass; /** * Creates a new Pool instance * @param max Max number of handler threads * @param workerClass Name of Worker implementation * @throws Exception */ public Pool (int max, Class workerClass) throws Exception { _max = max; _waiting = new Stack(); _workerClass = workerClass; Worker worker; WorkerThread w; for ( int i = 0; i < _max; i++ ) { worker = (Worker)_workerClass.newInstance(); w = new WorkerThread ("Worker#"+i, worker); w.start(); _waiting.push (w); } } /** * Request the Pool to perform some work. * @param data Data to give to the Worker * @return void * @throws InstantiationException Thrown if additional worker can't be created */ public void performWork (Object data) throws InstantiationException { WorkerThread w = null; synchronized (_waiting) { if ( _waiting.empty() ) { try { w = new WorkerThread ( "additional worker", (Worker)_workerClass.newInstance()); w.start(); } catch (Exception e) { throw new InstantiationException( "Problem creating instance of Worker.class: " + e.getMessage()); } } else { w = (WorkerThread)_waiting.pop(); } } w.wake (data); } /** * Convience method used by WorkerThread * to put Thread back on the stack * @param w WorkerThread to push * @return boolean True if pushed, false otherwise */ private boolean _push (WorkerThread w) { boolean stayAround = false; synchronized (_waiting) { if ( _waiting.size() < _max ) { stayAround = true; _waiting.push (w); } } return stayAround; } }