KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jdo > spi > persistence > support > sqlstore > utility > Timer


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24 /*
25  * Timer.java
26  *
27  * Create on March 3, 2000
28  */

29
30 package com.sun.jdo.spi.persistence.support.sqlstore.utility;
31
32 /**
33  * This class represents an asynchronous interval timer.
34  * The timer waits for a specified interval, then posts a
35  * tick event, called a <code>tick</code>, to a
36  * <code>TickEventListener</code> object that you create.
37  * Once the timer is started, it continues
38  * producing tick events at each interval until it is stopped.
39  * <p>
40  * To use a timer, you define a class that implements the
41  * <code>TickEventListener</code> interface. In the <code>tick</code>
42  * method, you write the code that
43  * that performs an action when the timer interval expires.
44  * <p>
45  * You then instantiate an object of your class
46  * and use it to start the timer and set the interval. For example:
47  * <pre>
48  * public class TimerUser implements TickEventListener
49  * {
50  * public Timer myTimer;
51  *
52  * public void startTimer(int interval, int active)
53  * {
54  * myTimer =
55  * new Timer(this, interval, (active == 1) ? true : false);
56  * }
57  *
58  * public void stopTimer()
59  * {
60  * if (myTimer != null)
61  * myTimer.setState(false);
62  * }
63  *
64  * public void tick(TickEvent evt)
65  * {
66  * System.out.println(
67  * "Tick count is " + evt.timer.getTickCount());
68  * }
69  * }
70  * </pre>
71  * @see com.forte.util.TickEventListener
72  * @see com.forte.util.TickEvent
73  */

74 public class Timer extends Object JavaDoc implements Runnable JavaDoc
75 {
76     /**
77     * The thread running this object.
78     */

79     private Thread JavaDoc runner;
80     
81     /**
82     * True when the alarm is armed.
83     */

84     private boolean active;
85
86     /**
87     * True when used for single tick
88     */

89     private boolean tickOnce;
90
91     /**
92     * The timer interval in milliseconds.
93     */

94     private long interval;
95
96     /**
97     * The number timer intervals expired.
98     */

99     private long ticks;
100
101     /**
102     * The owning object that will get the callback.
103     */

104     private TickEventListener owner;
105
106     /**
107     * True when the timer is terminating.
108     */

109     private boolean isTerminated;
110
111     /**
112      * @ForteInternal
113      * The number of times ForteThreads have suspended to wait for an
114      * installed timer to time out. This will be used as value for
115      * TimeOutSuspends instrument of the TaskMgr agent.
116      */

117     public static int suspends = 0;
118     
119     /**
120      * @ForteInternal
121      * The number of times ForteThreads have resumed after waiting for an
122      * installed timer to time out. This will be used as value for
123      * TimeOutResumes instrument of the TaskMgr agent.
124      */

125     public static int resumes = 0;
126
127
128     /**
129      * Constructs a timer object that is ready to be run.
130      * .
131      * @param active causes the timer to become active (<code>true</code>)
132      * or inactive (<code>false</code>).
133      * @param interval the timeout in milliseconds (1000 = 1 second).
134      * @param obj a listener for a TickEvent.
135      * @param tickOnce indicates that the TickEvent will only be
136      * delivered once (the default is repeated delivery on each tick).
137      */

138     public Timer(TickEventListener obj, long interval, boolean active)
139     {
140         this(obj, interval, active, false, null);
141     }
142
143     public Timer(TickEventListener obj, long interval, boolean active,
144                  boolean tickOnce, String JavaDoc name)
145     {
146         Thread JavaDoc thd;
147         this.owner = obj;
148         this.interval = interval;
149         this.active = active;
150         this.tickOnce = tickOnce;
151         this.isTerminated = false;
152         thd = new Thread JavaDoc(this);
153         thd.setDaemon(true);
154         if (name != null)
155         {
156             thd.setName(name);
157         }
158         else
159         {
160             thd.setName("TimerThread" + System.identityHashCode(this)); // NOI18N
161
}
162         thd.start();
163     }
164
165     /**
166      * Sets the interval in milliseconds between ticks of the timer.
167      *
168      * @param interval the new interval in milliseconds.
169      */

170     public void setInterval(long interval)
171     {
172         synchronized(this)
173         {
174             if (this.interval == interval)
175                 return;
176
177             this.interval = interval;
178
179             if (this.active)
180                 this.runner.interrupt();
181         }
182     }
183
184     /**
185      * Gets the current interval between ticks (in milliseconds).
186      *
187      * @return The current interval between ticks (in milliseconds).
188      */

189     //
190
// CHANGES
191
// 17-jun-1997
192
// Created (jak)
193
//
194
public long getInterval()
195     {
196         return this.interval;
197     }
198
199     /**
200      * Gets the number of ticks that have accumulated.
201     * @return The number of accumulated ticks.
202      */

203     //
204
// CHANGES
205
// 17-jun-1997
206
// Created (jak)
207
//
208
public long getTickCount()
209     {
210         return this.ticks;
211     }
212
213     /**
214      * Resets the number of ticks that have occurred to
215      * the specified number.
216      *
217      * @param count the new tick count.
218      */

219     //
220
// CHANGES
221
// 17-jun-1997
222
// Created (jak)
223
//
224
public void setTickCount(long count)
225     {
226         this.ticks = count;
227     }
228
229     /**
230      * Turns the timer on or off, enabling or disabling the
231      * delivery of tick events to the tick event listener.
232      *
233      * @param state causes the timer to become active (<code>true</code>)
234      * or inactive (<code>false</code>).
235      */

236     //
237
// CHANGES
238
// 17-jun-1997
239
// Created (jak)
240
//
241
public void setState(boolean state)
242     {
243         synchronized(this)
244         {
245             if (this.active == state)
246                 return;
247
248             if (this.active)
249                 this.runner.interrupt();
250             else
251                 this.notify();
252
253             this.active = state;
254         }
255     }
256
257     /**
258      * Terminate the timer (disable it).
259      */

260     //
261
// CHANGES
262
// 31-aug-1999
263
// Created (ncg)
264
//
265
public void terminate()
266     {
267         synchronized(this)
268         {
269             this.isTerminated = true;
270             if (this.runner != null)
271                 this.setState(false);
272         }
273     }
274
275     /**
276      * Run the thread and make sure cleanup happens.
277      */

278     public void run()
279     {
280         try
281         {
282             this.runMe();
283         }
284         finally
285         {
286             this.cleanForGC();
287         }
288     }
289
290     /**
291      * Runs the timer thread.
292      */

293     void runMe()
294     {
295         /* Thread runThread;
296
297         // Volatile check to see if terminated before we actually start.
298         if (this.isTerminated)
299         {
300             return;
301         }
302
303         this.runner = runThread = Thread.currentThread();
304
305         while (true)
306         {
307             synchronized(this)
308             {
309                 // Safe check to see if terminated before we actually run.
310                 if (this.isTerminated)
311                 {
312                     part.modifyDaemonCount(-1);
313                     return;
314                 }
315
316                 while (!this.active)
317                 {
318                     try
319                     {
320                         // Wait to become active.
321                         this.wait();
322                     }
323                     catch (InterruptedException ie)
324                     {
325                         if (this.runner == null || this.isTerminated)
326                         {
327                             part.modifyDaemonCount(-1);
328                             return;
329                         }
330                         if (runThread.isKilledOn())
331                         {
332                             part.modifyDaemonCount(-1);
333                             runThread.isKilled();
334                             return;
335                         }
336                     }
337                 }
338             }
339
340             try
341             {
342                 // Wait for out timeout.
343                 Timer.suspends++;
344                 runThread.sleep(this.interval);
345             }
346             catch(InterruptedException ie)
347             {
348                 if (this.runner == null || this.isTerminated)
349                 {
350                     part.modifyDaemonCount(-1);
351                     return;
352                 }
353                 if (runThread.isKilledOn())
354                 {
355                     part.modifyDaemonCount(-1);
356                     runThread.isKilled();
357                     return;
358                 }
359
360                 // Some internal state changed, skip the tick.
361                 continue;
362             }
363
364             this.ticks++;
365             Timer.resumes++;
366             TickEventListener theOwner; // local copy to avoid races
367             if ((theOwner = this.owner) != null)
368                  theOwner.tick(new TickEvent(this));
369
370             if (this.tickOnce || this.isTerminated)
371             {
372                 part.modifyDaemonCount(-1);
373                 return;
374             }
375         }
376
377         */

378     }
379
380     /**
381      * Clen up.
382      */

383     private void cleanForGC()
384     {
385         this.owner = null;
386         this.runner = null;
387     }
388
389     /**
390      * Kills the thread running the timer and destroys the timer object.
391      */

392     public void destroy()
393     {
394         try
395         {
396             this.cleanForGC();
397             Thread JavaDoc runThread;
398             if ((runThread = this.runner) != null)
399             {
400                 // runThread.stopThread();
401
}
402         }
403         catch (Exception JavaDoc e)
404         {
405         }
406     }
407
408     /**
409      * Destroys the timer.
410      *
411      */

412     public void finalize()
413     {
414         this.destroy();
415     }
416 }
417
Popular Tags