/*
* Copyright (c) 1998 - 2005 Versant Corporation
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Versant Corporation - initial API and implementation
*/
import java.util.LinkedList;
import java.util.Iterator;
import java.util.HashSet;
/**
* Simple pool of Threads.
*/
public class ThreadPool {
private String name;
private HashSet active = new HashSet();
private LinkedList idle = new LinkedList();
private int idleCount;
private int maxActive = 10;
private int maxIdle = 3;
private int lastThreadId;
private boolean closed;
public ThreadPool(String name) {
this.name = name;
}
public int getMaxActive() {
return maxActive;
}
public void setMaxActive(int maxActive) {
this.maxActive = maxActive;
}
public int getMaxIdle() {
return maxIdle;
}
public void setMaxIdle(int maxIdle) {
this.maxIdle = maxIdle;
}
public synchronized int getActiveCount() {
return active.size();
}
public synchronized int getIdleCount() {
return idleCount;
}
/**
* Close the pool, stopping all threads. This does not wait for the
* threads to actually stop before returning. This is a NOP if the
* pool has already been closed.
*/
public synchronized void close() {
if (closed) {
return;
}
closed = true;
for (Iterator i = idle.iterator(); i.hasNext(); ) {
Worker w = (Worker)i.next();
w.terminate();
}
idle = null;
idleCount = 0;
for (Iterator i = active.iterator(); i.hasNext(); ) {
Worker w = (Worker)i.next();
w.terminate();
}
active = null;
}
/**
* Executed runnable using a Thread from the pool. This will block for
* timeoutMs and forever if this is 0. Returns true if the task is
* being executed (i.e. a Thread was available) or false if not (i.e.
* pool full).
*/
public synchronized boolean execute(Runnable runnable, int timeoutMs) {
if (closed) {
throw new IllegalStateException("Pool has been closed");
}
Worker t;
if (idleCount == 0) {
for (; isFull(); ) {
try {
wait(timeoutMs);
if (isFull()) {
return false;
}
} catch (InterruptedException e) {
// ignore
}
}
t = new Worker();
} else {
t = (Worker)idle.removeFirst();
--idleCount;
}
active.add(t);
t.execute(runnable);
return true;
}
protected boolean isFull() {
return active.size() >= maxActive;
}
private synchronized void finishedWork(Worker t) {
if (!closed) {
active.remove(t);
if (idleCount >= maxIdle) {
t.terminate();
} else {
idle.addLast(t);
++idleCount;
}
}
}
private class Worker extends Thread {
private boolean stopFlag;
private Runnable runnable;
public Worker() {
super(name + " " + ++lastThreadId);
setDaemon(true);
}
/**
* Executed runnable.
*/
public void execute(Runnable runnable) {
this.runnable = runnable;
if (!isAlive()) {
start();
} else {
synchronized (this) {
notify();
}
}
}
/**
* Stop this thread as soon as possible.
*/
public void terminate() {
stopFlag = true;
interrupt();
}
public void run() {
for (; !stopFlag; ) {
try {
runnable.run();
} catch (Throwable e) {
if (e instanceof ThreadDeath) {
throw (ThreadDeath)e;
}
}
runnable = null;
finishedWork(this);
if (stopFlag) break;
synchronized (this) {
try {
wait();
} catch (InterruptedException e) {
// ignore
}
}
}
}
}
}
|