SchedulerQueue.java :  » Web-Server » simple » simple » util » schedule » Java Open Source

Java Open Source » Web Server » simple 
simple » simple » util » schedule » SchedulerQueue.java
/*
 * SchedulerQueue.java February 2001
 *
 * Copyright (C) 2001, Niall Gallagher <niallg@users.sf.net>
 *
 * 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.
 *
 * 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
 */

package simple.util.schedule;

import simple.util.PriorityQueue;

/**
 * This is a <code>SchedulerQueue</code> used to prioritize objects
 * enqueued. This queue is a <code>PriorityQueue</code>. It ensures
 * the object with the highest priority value will leave the queue
 * first, this also ensures that a null item is never dequeued.
 * <p>
 * This prioritizes the entry into a <code>PriorityQueue</code> so
 * that objects that are removed can be synchronized if there are
 * multiple threads removing from the queue. It is important to
 * note that this should not cap the prioritys be cause the queue
 * that is being used will only remove objects that are highest
 * in priority at the moment of <code>PriorityQueue.dequeue</code>
 * so if the prioritys are all capped then it becomes impossible
 * to remove some of the items from the queue.
 *
 * @author Niall Gallagher
 *
 * @see simple.util.PriorityQueue
 */
final class SchedulerQueue {

   /**
    * This will schedule the objects on priority.
    */
   private PriorityQueue queue;

   /**
    * This is a lock so there can be concurrency.
    */
   private Object lock;

   /**
    * This counts the no of threads waiting.
    */
   private int dequeuers;

   /**
    * This creates a new <code>SchedulerQueue</code> object for
    * scheduling objects that are queued. The objects that are
    * queued have a maximum and a minimum priority that they can
    * be set to. All prioritys are capped to be inside this range.
    */
   public SchedulerQueue() {
      this.queue = new PriorityQueue();
      this.lock = new Object();
   }

   /**
    * This method is for enqueuing objects. If the priority
    * specified is larger than the largest priority allowed
    * then the priority is capped to the maximum priority,
    * the priority is also capped to the minimum of the queue.
    *
    * @param obj the object to be scheduled in the queue
    * @param priority the priority of the object to be queued
    */
   public void enqueue(Object obj, long priority) {
      synchronized(lock){
         enqueuing();
         queue.add(obj, priority);
      }
   }

   /**
    * This is guaranteed to return an object. If the queue is
    * empty then the thread that is dequeuing blocks until there
    * is an object to dequeue, it will be notified by the enqueuer.
    *
    * @throws InterruptedException thrown if theres an interrupt
    *
    * @return the object with the highest priority in the queue
    */
   public Object dequeue() throws InterruptedException {
      synchronized(lock){
         dequeuing();
         return queue.remove();
      }
   }

   /**
    * This will determine wheather the current thread must block and
    * wait for an object. The semantics of the wait notify paradigm is
    * such that this check must be iterative. When there are no objects
    * in the queue then a dequeuer will wait on the lock. However once
    * an object is enqueued then the thread that was waiting is
    * notified. This does not mean that the thread that was notified
    * will be the thread that grabs the lock next. In fact the notified
    * thread must compete with all other threads to grab the lock. This
    * means that while the notified thread is attempting to grab the
    * lock another thread may scoop the object that was enqueued. The
    * check must be made iteratively so that this occurance does not
    * cause the queue to return null, the dequeuer count is changed
    * within a lock.
    *
    * @throws InterruptedException thrown if the thread is
    * interrupted
    */
   private void dequeuing() throws InterruptedException {
      while(queue.length() == 0) {
         dequeuers++;
         try{
            lock.wait();
         }finally{
            dequeuers--;
         }
      }
   }

   /**
    * This notifys any waiting thread that there is an object to
    * dequeue. This may be called when all the dequeuers have been
    * notified. This is because the dequeuer must grab the lock
    * before it can decrement the dequeuers variable, this is not
    * really that wasteful.
    */
   private void enqueuing() {
      if(dequeuers > 0) {
         lock.notify();
      }
   }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.