Mega Code Archive

 
Categories / Java / Threads
 

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();   } }