View Javadoc

    1   /***
    2    * @(#)TaskScheduler.java
    3    *
    4    * JFoxSOAF, Service-Oriented Application Framework
    5    *
    6    * Copyright(c) JFoxSOAF Team
    7    *
    8    * Licensed under the GNU LGPL, Version 2.1 (the "License");
    9    * you may not use this file except in compliance with the License.
    10   * You may obtain a copy of the License at
    11   *
    12   * http://www.gnu.org/copyleft/lesser.html
    13   *
    14   * Unless required by applicable law or agreed to in writing, software
    15   * distributed under the License is distributed on an "AS IS" BASIS,
    16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    17   * See the License for the specific language governing permissions and
    18   * limitations under the License.
    19   *
    20   * For more information, please visit:
    21   * http://www.jfox.cn/confluence/display/JFoxSOAF/Home
    22   * http://www.huihoo.org/jfox/jfoxsoaf
    23   */
    24
    25  package org.huihoo.jfox.soaf.services.timer;
    26
    27  import java.util.ArrayList;
    28  import java.util.Date;
    29  import java.util.Timer;
    30  import java.util.TimerTask;
    31
    32  /***
    33   * Class for running Tasks with scheduling/thread pooling etc. <br>
    34   * <p>
    35   * The tasks are Task objects. A user would extend the Task class and override
    36   * the abstract methods ( e.g. its run() method ).
    37   * </p>
    38   * <p>
    39   * Persistence of the Task objects allows the TaskScheduler to be shutdown and
    40   * restarted with all the scheduled tasks read from storage.
    41   * </p>
    42   *
    43   * @author <a href="mailto:founder_chen@yahoo.com.cn">Peter Cheng </a>
    44   * @author <a href="mailto:berkovichnyc@hotmail.com">Efraim Berkovich </a>
    45   * @version $Revision: 1.1 $ $Date: 2005/05/22 06:52:07 $
    46   * @version Revision: 1.0
    47   */
    48
    49  public class SimpleTimerServiceImpl implements SimpleTimerService {
    50
    51      // instance variables
    52      private Timer schedulerThread;
    53
    54      private ArrayList taskList;
    55
    56      private long initTime;
    57
    58      private TaskPersistStrategy persistStrategy = null;
    59
    60      //  static variables
    61      private static Boolean semaphore = new Boolean(true);
    62
    63      /***
    64       * Shutdown the scheduler
    65       */
    66      public void shutdown() {
    67          synchronized (semaphore) {
    68              this.schedulerThread.cancel();
    69          }
    70      }
    71
    72      /***
    73       * Create a task scheduler with a default thread pool size.
    74       */
    75      public SimpleTimerServiceImpl() {
    76          schedulerThread = new Timer(false);
    77          initTime = System.currentTimeMillis();
    78          taskList = new ArrayList();
    79      }
    80
    81      /***
    82       * Set the particular methodology for persisting Tasks
    83       *
    84       * @param strategy The TaskPersistStrategy to use
    85       */
    86      public void setPersistStrategy(TaskPersistStrategy strategy) {
    87          synchronized (this) {
    88              persistStrategy = strategy;
    89          }
    90      }
    91
    92      /***
    93       * Get the time the TaskScheduler was started.
    94       *
    95       * @return the time (in millis) when the Scheduler was started.
    96       */
    97      public long getSchedulerStartTime() {
    98          return initTime;
    99      }
    100
    101     /***
    102      * Schedules the specified task for execution according to the task's
    103      * scheduling properties.
    104      *
    105      * @param task The task to schedule for execution.
    106      * @exception IllegalStateException if task was already scheduled or
    107      *                cancelled, timer was cancelled, or timer thread
    108      *                terminated.
    109      * @exception Exception if cannot persist task
    110      */
    111     public void schedule(Task task) throws IllegalStateException, Exception {
    112         synchronized (this) {
    113             cleanupAll();
    114             if (taskList.contains(task))
    115                 throw new IllegalStateException("Task was already scheduled");
    116
    117             Date time = new Date(task.getScheduledFirstTime());
    118
    119             RunTask runTask = new RunTask(task);
    120
    121             if (task.getScheduledInterval() <= 0) {
    122                 schedulerThread.schedule(runTask, time);
    123             } else {
    124                 schedulerThread.scheduleAtFixedRate(runTask, time, task
    125                         .getScheduledInterval());
    126             }
    127
    128             task.scheduler = this;
    129             taskList.add(task);
    130
    131             this.persist(task);
    132         }
    133     }
    134
    135     /***
    136      * Cancel all executing tasks and timer threads.
    137      *
    138      * @param withRestart if true, all timer threads will restart; however, all
    139      *            scheduled task will have been cancelled.
    140      */
    141     public void cancelAll(boolean withRestart) {
    142         synchronized (this) {
    143             taskList.clear();
    144             schedulerThread.cancel();
    145
    146             if (withRestart)
    147                 schedulerThread = new Timer(false);
    148         }
    149     }
    150
    151     /***
    152      * Fetch all non-cancelled tasks at the time the method is called. If tasks
    153      * are cancelling during this time, some cancelled tasks may be returned.
    154      *
    155      * @return array of Tasks which are not cancelled
    156      */
    157     public Task[] getRunningTasks() {
    158         ArrayList list = new ArrayList();
    159         cleanupAll();
    160
    161         synchronized (this) {
    162             for (int i = 0; i < taskList.size(); i++) {
    163                 Task task = (Task) taskList.get(i);
    164                 if (!task.isCancelled()) {
    165                     list.add(task);
    166                 }
    167             }
    168         }
    169         Task[] out = new Task[list.size()];
    170         for (int i = 0; i < out.length; i++)
    171             out[i] = (Task) list.get(i);
    172
    173         return out;
    174     }
    175
    176     /***
    177      * Find a particular task by its ID
    178      *
    179      * @param taskID The task to find
    180      * @return Task for this ID or null if not found
    181      */
    182     public Task findTaskByID(long taskID) {
    183         synchronized (this) {
    184             for (int i = 0; i < taskList.size(); i++) {
    185                 Task task = (Task) taskList.get(i);
    186                 if (task.getID() == taskID) {
    187                     return task;
    188                 }
    189             }
    190         }
    191         return null;
    192     }
    193
    194     /***
    195      * Check and remove a particular task
    196      *
    197      * @param Task the potentially cancelled task to remove
    198      */
    199     void cleanup(Task task) {
    200         synchronized (this) {
    201             if (taskList.contains(task)) {
    202                 if (task.isCancelled()) {
    203                     taskList.remove(task);
    204                     if (persistStrategy != null)
    205                         persistStrategy.delete(task);
    206                 }
    207             }
    208         }
    209     }
    210
    211     /***
    212      * Persists the task by telling the persist strategy to do so
    213      *
    214      * @exception various possible depending on strategy
    215      */
    216     void persist(Task task) throws Exception {
    217         synchronized (this) {
    218             if (persistStrategy != null)
    219                 persistStrategy.write(task);
    220         }
    221     }
    222
    223     /***
    224      * Go through the taskList and eliminate cancelled tasks
    225      */
    226     private void cleanupAll() {
    227         synchronized (this) {
    228             for (int i = 0; i < taskList.size(); i++) {
    229                 Task task = (Task) taskList.get(i);
    230                 if (task.isCancelled()) {
    231                     taskList.remove(i);
    232                     if (persistStrategy != null)
    233                         persistStrategy.delete(task);
    234                     i--;
    235                 }
    236             }
    237         }
    238     }
    239
    240     /***
    241      * RunTask class is scheduler to on the Timer and is associated with a Task
    242      * which it runs.
    243      */
    244     private class RunTask extends TimerTask {
    245         // instance variables
    246         private Task task;
    247
    248         /***
    249          * Create a new RunTask
    250          *
    251          * @param task The Task to run
    252          */
    253         public RunTask(Task task) {
    254             this.task = task;
    255         }
    256
    257         /***
    258          * Run the Task
    259          */
    260         public void run() {
    261             if (task.isCancelled()) {
    262                 this.cancel();
    263                 return;
    264             }
    265
    266             // NOTE: TBD
    267             //    For now we just launch a thread to do the task.
    268             //    This is potentially not scaleable. In the future,
    269             //    we will pick threads from a pool.
    270
    271             Thread runner = new Thread(task);
    272             runner.start();
    273             task.setLastRunTime(System.currentTimeMillis());
    274         }
    275
    276     }
    277
    278 }