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
52 private Timer schedulerThread;
53
54 private ArrayList taskList;
55
56 private long initTime;
57
58 private TaskPersistStrategy persistStrategy = null;
59
60
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
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
267
268
269
270
271 Thread runner = new Thread(task);
272 runner.start();
273 task.setLastRunTime(System.currentTimeMillis());
274 }
275
276 }
277
278 }