KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mx4j > timer > TimeQueue


1 /*
2  * Copyright (C) MX4J.
3  * All rights reserved.
4  *
5  * This software is distributed under the terms of the MX4J License version 1.0.
6  * See the terms of the MX4J License in the documentation provided with this software.
7  */

8
9 package mx4j.timer;
10
11 import java.util.ArrayList JavaDoc;
12 import java.util.Collections JavaDoc;
13
14 /**
15  * A queue that executes {@link mx4j.timer.TimeTask}s when it is started. <br>
16  * Every scheduled task is executed at the specified time; if this time is in the past,
17  * the task is executed immediately.
18  * Just before the task is executed, the task itself is updated so that its new
19  * execution time is set or it is marked as finished (if it is not forever periodic).
20  *
21  * @see mx4j.timer.TimeTask
22  *
23  * @author <a HREF="mailto:biorn_steedom@users.sourceforge.net">Simone Bordet</a>
24  * @version $Revision: 1.1 $
25  */

26 public class TimeQueue
27 {
28    private Thread JavaDoc thread;
29    private volatile boolean running;
30    private final ArrayList JavaDoc tasks;
31
32    /**
33     * Creates a new TimeQueue
34     */

35    public TimeQueue()
36    {
37       tasks = new ArrayList JavaDoc();
38    }
39
40    /**
41     * Starts this TimeQueue. <br>
42     * Tasks are executed only after the queue has been started.
43     * @see #stop
44     */

45    public void start()
46    {
47       synchronized (this)
48       {
49          if (!running)
50          {
51             running = true;
52             thread = new Thread JavaDoc(new Loop(), "MBean Timer Notification Thread");
53             thread.setDaemon(true);
54             thread.start();
55          }
56       }
57    }
58
59    /**
60     * Stops this TimeQueue. <br>
61     * No task is executed when the queue is stopped; however, already scheduled tasks
62     * are not removed; restarting the queue has the effect of executing the tasks remained
63     * if their time has come.
64     * @see #start
65     */

66    public void stop()
67    {
68       synchronized (this)
69       {
70          if (running)
71          {
72             running = false;
73             thread.interrupt();
74          }
75       }
76    }
77
78    /**
79     * Returns the number of tasks present in this TimeQueue
80     */

81    public int size()
82    {
83       synchronized (this)
84       {
85          return tasks.size();
86       }
87    }
88
89    /**
90     * Schedules the given task for execution.
91     * @see #unschedule
92     */

93    public void schedule(TimeTask task)
94    {
95       synchronized (this)
96       {
97          tasks.add(task);
98          // Using tree sets or maps does not work, since they don't rely on equals for add, but on compareTo
99
Collections.sort(tasks);
100          notifyAll();
101       }
102    }
103
104    /**
105     * Removes the given task from this TimeQueue
106     * @see #schedule
107     */

108    public void unschedule(TimeTask task)
109    {
110       synchronized (this)
111       {
112          tasks.remove(task);
113       }
114    }
115
116    /**
117     * Removes all the tasks from this TimeQueue.
118     */

119    public void clear()
120    {
121       synchronized (this)
122       {
123          tasks.clear();
124       }
125    }
126
127    private TimeTask getTask() throws InterruptedException JavaDoc
128    {
129       synchronized (this)
130       {
131          while (tasks.isEmpty())
132          {
133             wait();
134          }
135
136          // Do not remove the task from the queue
137
TimeTask task = (TimeTask)tasks.get(0);
138          return task;
139       }
140    }
141
142    private class Loop implements Runnable JavaDoc
143    {
144       public void run()
145       {
146          while (running && !thread.isInterrupted())
147          {
148             try
149             {
150                TimeTask task = getTask();
151                long now = System.currentTimeMillis();
152                long executionTime = task.getNextExecutionTime();
153                long timeToWait = executionTime - now;
154                boolean runTask = timeToWait <= 0;
155                if (!runTask)
156                {
157                   // When a new job is scheduled, I wake up, but this job may not be the one to run
158
Object JavaDoc lock = TimeQueue.this;
159                   synchronized (lock)
160                   {
161                      // timeToWait is always strictly > 0, so I don't wait forever
162
lock.wait(timeToWait);
163                   }
164                }
165                else
166                {
167                   // The task must be run, remove it from the list
168
unschedule(task);
169
170                   if (task.isPeriodic())
171                   {
172                      // Compute the new execution time. This is different for
173
// fixed rate and fixed delay tasks
174
if (task.getFixedRate())
175                      {
176                         task.setNextExecutionTime(executionTime + task.getPeriod());
177                      }
178                      else
179                      {
180                         task.setNextExecutionTime(now + task.getPeriod());
181                      }
182
183                      // Reschedule on the new time
184
schedule(task);
185                   }
186                   else
187                   {
188                      // Mark the task as finished, it will be removed also by the Timer class
189
task.setFinished(true);
190                   }
191
192                   try
193                   {
194                      // Run it !
195
task.run();
196                   }
197                   catch (Throwable JavaDoc x)
198                   {
199                      // Problems, for now just print it
200
x.printStackTrace();
201                   }
202                }
203             }
204             catch (InterruptedException JavaDoc x)
205             {
206                Thread.currentThread().interrupt();
207                break;
208             }
209          }
210       }
211    }
212 }
213
Popular Tags