/**
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hphoto.util;
import java.util.*;
import java.util.logging.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/************************************************
* ThreadPool.java
*
* ThreadPool maintains a large set of threads, which
* can be dedicated to a certain task, and then recycled.
***********************************************/
public class ThreadPool {
/**
* A TaskThread sits in a loop, asking the pool
* for a job, and servicing it. That's all it does.
*/
class TaskThread extends Thread {
/**
* Get a job from the pool, run it, repeat.
* If the job is null, we exit the loop.
*/
public void run() {
while (true) {
Runnable r = obtainJob();
if (r == null) {
break;
}
try {
r.run();
} catch (Exception e) {
System.err.println("E: " + e);
e.printStackTrace();
}
}
}
}
int numThreads;
boolean running = false;
Vector jobs;
/**
* Creates a pool of numThreads size.
* These threads sit around waiting for jobs to
* be posted to the list.
*/
public ThreadPool(int numThreads) {
this.numThreads = numThreads;
jobs = new Vector(37);
running = true;
for (int i = 0; i < numThreads; i++) {
TaskThread t = new TaskThread();
t.start();
}
Log l = LogFactory.getLog(ThreadPool.class.getName());
l.fatal("ThreadPool created with " + numThreads + " threads.");
}
/**
* Gets a job from the queue, returns to worker thread.
* When the pool is closed down, return null for all
* obtainJob() requests. That tells the thread to
* shut down.
*/
Runnable obtainJob() {
Runnable job = null;
synchronized (jobs) {
while (job == null && running) {
try {
if (jobs.size() == 0) {
jobs.wait();
}
} catch (InterruptedException ie) {
}
if (jobs.size() > 0) {
job = (Runnable) jobs.firstElement();
jobs.removeElementAt(0);
}
}
}
if (running) {
// Got a job from the queue
return job;
} else {
// Shut down the pool
return null;
}
}
/**
* Post a Runnable to the queue. This will be
* picked up by an active thread.
*/
public void addJob(Runnable runnable) {
synchronized (jobs) {
jobs.add(runnable);
jobs.notifyAll();
}
}
/**
* Turn off the pool. Every thread, when finished with
* its current work, will realize that the pool is no
* longer running, and will exit.
*/
public void shutdown() {
running = false;
Log l = LogFactory.getLog(ThreadPool.class.getName());
l.fatal("ThreadPool shutting down.");
}
}