FileDocCategorySizeDatePackage
ThreadPool.javaAPI DocExample3705Thu Feb 04 16:10:44 GMT 1999None

ThreadPool.java

/*
 *
 * Copyright (c) 1997-1999 Scott Oaks and Henry Wong. 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.
 *
 * This sample source code is provided for example only,
 * on an unsupported, as-is basis. 
 *
 * AUTHOR 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. AUTHOR SHALL NOT BE LIABLE FOR
 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 *
 * THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
 * CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
 * PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
 * NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
 * SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
 * SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
 * PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES").  AUTHOR
 * SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR
 * HIGH RISK ACTIVITIES.
 */


import java.util.*;

public class ThreadPool {

	class ThreadPoolRequest {
		Runnable target;
		Object lock;

		ThreadPoolRequest(Runnable t, Object l) {
			target = t;
			lock = l;
		}
	}

	class ThreadPoolThread extends Thread {
		ThreadPool parent;
		ThreadPoolThread(ThreadPool parent, int i) {
			super("ThreadPoolThread " + i);
			setDaemon(true);
			this.parent = parent;
		}

		public void run() {
			ThreadPoolRequest obj = null;
			while (true) {
				try {
					parent.cvFlag.getBusyFlag();
					while (obj == null) {
						try {
							obj = (ThreadPoolRequest)
									parent.objects.elementAt(0);
							parent.objects.removeElementAt(0);
						} catch (ArrayIndexOutOfBoundsException aiobe) {
							obj = null;
						} catch (ClassCastException cce) {
							System.err.println("Unexpected data");
							obj = null;
						}
						if (obj == null) {
							try {
								parent.cvAvailable.cvWait();
							} catch (InterruptedException ie) {
								return;
							}
						}
					}
				} finally {
					parent.cvFlag.freeBusyFlag();
				}
				obj.target.run();
				try {
					parent.cvFlag.getBusyFlag();
					nObjects--;
					if (nObjects == 0)
						parent.cvEmpty.cvSignal();
				} finally {
					parent.cvFlag.freeBusyFlag();
				}
				if (obj.lock != null) {
					synchronized(obj.lock) {
						obj.lock.notify();
					}
				}
				obj = null;
			}
		}
	}

	Vector objects;
	int	nObjects = 0;
	CondVar cvAvailable, cvEmpty;
	BusyFlag cvFlag;

	public ThreadPool(int n) {
		cvFlag = new BusyFlag();
		cvAvailable = new CondVar(cvFlag);
		cvEmpty = new CondVar(cvFlag);
		objects = new Vector();
		for (int i = 0; i < n; i++)
			new ThreadPoolThread(this, i).start();
	}

	private void add(Runnable target, Object lock) {
		try {
			cvFlag.getBusyFlag();
			objects.addElement(new ThreadPoolRequest(target, lock));
			nObjects++;
			cvAvailable.cvSignal();
		} finally {
			cvFlag.freeBusyFlag();
		}
	}

	public void addRequest(Runnable target) {
		add(target, null);
	}

	public void addRequestAndWait(Runnable target)
							throws InterruptedException {
		Object lock = new Object();
		synchronized(lock) {
			add(target, lock);
			lock.wait();
		}
	}

	public void waitForAll() throws InterruptedException {
		try {
			cvFlag.getBusyFlag();
			while (nObjects != 0)
				cvEmpty.cvWait();
		} finally {
			cvFlag.freeBusyFlag();
		}
	}
}