Worker thread pool
/**
*
* JFreeReport : a free Java reporting library
*
*
* Project Info: http://reporting.pentaho.org/
*
* (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
*
* This library is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* [Java is a trademark or registered trademark of Sun Microsystems, Inc.
* in the United States and other countries.]
*
* ------------
* WorkerPool.java
* ------------
* (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
*/
/**
* A simple static workpool. Worker threads are created when necessary.
*
* @author Thomas Morgner
*
*/
public class WorkerPool
{
/**
* The worker array.
*/
private Worker[] workers;
/**
* A flag indicating whether idle workers are available.
*/
private boolean workersAvailable;
/**
* the name prefix for all workers of this pool.
*/
private String namePrefix;
/**
* Creates a new worker pool with the default size of 10 workers and the default name.
*/
public WorkerPool ()
{
this(10);
}
/**
* Creates a new workerpool with the given number of workers and the default name.
*
* @param size the maximum number of workers available.
*/
public WorkerPool (final int size)
{
this(size, "WorkerPool-worker");
}
/**
* Creates a new worker pool for the given number of workers and with the given name
* prefix.
*
* @param size the size of the worker pool.
* @param namePrefix the name prefix for all created workers.
*/
public WorkerPool (final int size, final String namePrefix)
{
if (size <= 0)
{
throw new IllegalArgumentException("Size must be > 0");
}
workers = new Worker[size];
workersAvailable = true;
this.namePrefix = namePrefix;
}
/**
* Checks whether workers are available.
*
* @return true, if at least one worker is idle, false otherwise.
*/
public synchronized boolean isWorkerAvailable ()
{
return workersAvailable;
}
/**
* Updates the workersAvailable flag after a worker was assigned.
*/
private void updateWorkersAvailable ()
{
for (int i = 0; i < workers.length; i++)
{
if (workers[i] == null)
{
workersAvailable = true;
return;
}
if (workers[i].isAvailable() == true)
{
workersAvailable = true;
return;
}
}
workersAvailable = false;
}
/**
* Waits until a worker will be available.
*/
private synchronized void waitForWorkerAvailable ()
{
while (isWorkerAvailable() == false)
{
try
{
// remove lock
this.wait(5000);
}
catch (InterruptedException ie)
{
// ignored
}
}
}
/**
* Returns a workerhandle for the given workload. This method will wait until an idle
* worker is found.
*
* @param r the workload for the worker
* @return a handle to the worker.
*/
public synchronized WorkerHandle getWorkerForWorkload (final Runnable r)
{
waitForWorkerAvailable();
int emptySlot = -1;
for (int i = 0; i < workers.length; i++)
{
if (workers[i] == null)
{
// in the first run, try to avoid to create new threads...
// reuse the already available threads
if (emptySlot == -1)
{
emptySlot = i;
}
continue;
}
if (workers[i].isAvailable() == true)
{
workers[i].setWorkload(r);
updateWorkersAvailable();
return new WorkerHandle(workers[i]);
}
}
if (emptySlot != -1)
{
workers[emptySlot] = new Worker();
workers[emptySlot].setName(namePrefix + '-' + emptySlot);
workers[emptySlot].setWorkerPool(this);
workers[emptySlot].setWorkload(r);
updateWorkersAvailable();
return new WorkerHandle(workers[emptySlot]);
}
throw new IllegalStateException
("At this point, a worker should already have been assigned.");
}
/**
* Marks the given worker as finished. The worker will be removed from the list of the
* available workers.
*
* @param worker the worker which was finished.
*/
public void workerFinished (final Worker worker)
{
if (worker.isFinish() == false)
{
throw new IllegalArgumentException("This worker is not in the finish state.");
}
for (int i = 0; i < workers.length; i++)
{
if (workers[i] == worker)
{
synchronized (this)
{
workers[i] = null;
workersAvailable = true;
this.notifyAll();
}
return;
}
}
}
/**
* Marks the given worker as available.
*
* @param worker the worker which was available.
*/
public synchronized void workerAvailable (final Worker worker)
{
for (int i = 0; i < workers.length; i++)
{
if (workers[i] == worker)
{
synchronized (this)
{
workersAvailable = true;
this.notifyAll();
}
return;
}
}
}
/**
* Finishes all worker of this pool.
*/
public void finishAll ()
{
for (int i = 0; i < workers.length; i++)
{
if (workers[i] != null)
{
workers[i].finish();
}
}
}
}
/**
*
* JFreeReport : a free Java reporting library
*
*
* Project Info: http://reporting.pentaho.org/
*
* (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
*
* This library is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* [Java is a trademark or registered trademark of Sun Microsystems, Inc.
* in the United States and other countries.]
*
* ------------
* Worker.java
* ------------
* (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
*/
/**
* A simple worker implementation. The worker executes a assigned workload and then sleeps
* until another workload is set or the worker is killed.
*
* @author Thomas Morgner
*/
final class Worker extends Thread
{
/**
* the worker's task.
*/
private Runnable workload;
/**
* a flag whether the worker should exit after the processing.
*/
private volatile boolean finish;
/**
* the time in milliseconds beween 2 checks for exit or work requests.
*/
private final int sleeptime;
/**
* The worker pool, to which this worker is assigned. May be null.
*/
private WorkerPool workerPool;
/**
* Creates a new worker.
*
* @param sleeptime the time this worker sleeps until he checks for new work.
*/
public Worker (final int sleeptime)
{
this.sleeptime = sleeptime;
this.setDaemon(true);
start();
}
/**
* Creates a new worker with an default idle timeout of 2 minutes.
*/
public Worker ()
{
this(120000);
}
/**
* Set the next workload for this worker.
*
* @param r the next workload for the worker.
* @throws IllegalStateException if the worker is not idle.
*/
public void setWorkload (final Runnable r)
{
if (workload != null)
{
throw new IllegalStateException("This worker is not idle.");
}
//Log.debug("Workload set...");
synchronized (this)
{
workload = r;
//Log.debug("Workload assigned: Notified " + getName());
this.notifyAll();
}
}
/**
* Returns the workload object.
*
* @return the runnable executed by this worker thread.
*/
public synchronized Runnable getWorkload()
{
return workload;
}
/**
* Kills the worker after he completed his work. Awakens the worker if he's sleeping, so
* that the worker dies without delay.
*/
public void finish ()
{
finish = true;
// we are evil ..
try
{
this.interrupt();
}
catch (SecurityException se)
{
// ignored
}
if (workerPool != null)
{
workerPool.workerFinished(this);
}
}
/**
* Checks whether this worker has some work to do.
*
* @return true, if this worker has no more work and is currently sleeping.
*/
public boolean isAvailable ()
{
return (workload == null);
}
/**
* If a workload is set, process it. After the workload is processed, this worker starts
* to sleep until a new workload is set for the worker or the worker got the finish()
* request.
*/
public void run ()
{
while (!finish)
{
if (workload != null)
{
try
{
workload.run();
}
catch (Exception e)
{
System.out.println("Worker caught exception on run: "+ e);
}
workload = null;
if (workerPool != null)
{
workerPool.workerAvailable(this);
}
}
if (!finish)
{
synchronized (this)
{
try
{
// remove lock
this.wait(sleeptime);
}
catch (InterruptedException ie)
{
// ignored
}
}
}
}
synchronized (this)
{
this.notifyAll();
}
}
/**
* Checks whether this worker has received the signal to finish and die.
*
* @return true, if the worker should finish the work and end the thread.
*/
public boolean isFinish ()
{
return finish;
}
/**
* Returns the worker's assigned pool.
*
* @return the worker pool (or null, if the worker is not assigned to a pool).
*/
public WorkerPool getWorkerPool ()
{
return workerPool;
}
/**
* Defines the worker's assigned pool.
*
* @param workerPool the worker pool (or null, if the worker is not assigned to a
* pool).
*/
public void setWorkerPool (final WorkerPool workerPool)
{
this.workerPool = workerPool;
}
}
/**
*
* JFreeReport : a free Java reporting library
*
*
* Project Info: http://reporting.pentaho.org/
*
* (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
*
* This library is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* [Java is a trademark or registered trademark of Sun Microsystems, Inc.
* in the United States and other countries.]
*
* ------------
* WorkerHandle.java
* ------------
* (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
*/
/**
* The worker handle is a control structure which allows control over the worker without
* exposing the thread object.
*
* @author Thomas Morgner
* @deprecated This class is used by the WorkerPool, which is not used anywhere anymore.
*/
class WorkerHandle
{
/**
* The worker for this handle.
*/
private final Worker worker;
/**
* Creates a new handle for the given worker.
*
* @param worker the worker.
*/
public WorkerHandle (final Worker worker)
{
this.worker = worker;
}
/**
* Finishes the worker.
*/
public void finish ()
{
worker.finish();
}
}
Related examples in the same category