* java/util/Timer.java: New version from Classpath.
From-SVN: r39573
This commit is contained in:
parent
0e206b71aa
commit
932670198f
2 changed files with 503 additions and 436 deletions
|
@ -1,3 +1,7 @@
|
|||
2001-02-09 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
* java/util/Timer.java: New version from Classpath.
|
||||
|
||||
2001-02-09 Bryce McKinlay <bryce@albatross.co.nz>
|
||||
|
||||
* java/lang/Double.java (doubleToRawLongBits): Now native.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Timer.java -- Timer that runs TimerTasks at a later time.
|
||||
Copyright (C) 2000 Free Software Foundation, Inc.
|
||||
Copyright (C) 2000, 2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
|
@ -7,7 +7,7 @@ GNU Classpath is free software; you can redistribute it and/or modify
|
|||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
|
||||
GNU Classpath 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
|
||||
|
@ -50,476 +50,539 @@ package java.util;
|
|||
* @since 1.3
|
||||
* @author Mark Wielaard (mark@klomp.org)
|
||||
*/
|
||||
public class Timer {
|
||||
public class Timer
|
||||
{
|
||||
/**
|
||||
* Priority Task Queue.
|
||||
* TimerTasks are kept in a binary heap.
|
||||
* The scheduler calls sleep() on the queue when it has nothing to do or
|
||||
* has to wait. A sleeping scheduler can be notified by calling interrupt()
|
||||
* which is automatically called by the enqueue(), cancel() and
|
||||
* timerFinalized() methods.
|
||||
*/
|
||||
private static final class TaskQueue
|
||||
{
|
||||
/** Default size of this queue */
|
||||
private final int DEFAULT_SIZE = 32;
|
||||
|
||||
/** Wheter to return null when there is nothing in the queue */
|
||||
private boolean nullOnEmpty;
|
||||
|
||||
/**
|
||||
* Priority Task Queue.
|
||||
* TimerTasks are kept in a binary heap.
|
||||
* The scheduler calls sleep() on the queue when it has nothing to do or
|
||||
* has to wait. A sleeping scheduler can be notified by calling interrupt()
|
||||
* which is automatically called by the enqueue(), cancel() and
|
||||
* timerFinalized() methods.
|
||||
* The heap containing all the scheduled TimerTasks
|
||||
* sorted by the TimerTask.scheduled field.
|
||||
* Null when the stop() method has been called.
|
||||
*/
|
||||
private static final class TaskQueue {
|
||||
|
||||
/** Default size of this queue */
|
||||
private final int DEFAULT_SIZE = 32;
|
||||
|
||||
/** Wheter to return null when there is nothing in the queue */
|
||||
private boolean nullOnEmpty;
|
||||
|
||||
/**
|
||||
* The heap containing all the scheduled TimerTasks
|
||||
* sorted by the TimerTask.scheduled field.
|
||||
* Null when the stop() method has been called.
|
||||
*/
|
||||
private TimerTask heap[];
|
||||
|
||||
/**
|
||||
* The actual number of elements in the heap
|
||||
* Can be less then heap.length.
|
||||
* Note that heap[0] is used as a sentinel.
|
||||
*/
|
||||
private int elements;
|
||||
|
||||
/**
|
||||
* Creates a TaskQueue of default size without any elements in it.
|
||||
*/
|
||||
public TaskQueue() {
|
||||
heap = new TimerTask[DEFAULT_SIZE];
|
||||
elements = 0;
|
||||
nullOnEmpty = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a TimerTask at the end of the heap.
|
||||
* Grows the heap if necessary by doubling the heap in size.
|
||||
*/
|
||||
private void add(TimerTask task) {
|
||||
elements++;
|
||||
if (elements == heap.length) {
|
||||
TimerTask new_heap[] = new TimerTask[heap.length*2];
|
||||
System.arraycopy(heap, 0, new_heap, 0, heap.length);
|
||||
heap = new_heap;
|
||||
}
|
||||
heap[elements] = task;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the last element from the heap.
|
||||
* Shrinks the heap in half if
|
||||
* elements+DEFAULT_SIZE/2 <= heap.length/4.
|
||||
*/
|
||||
private void remove() {
|
||||
// clear the entry first
|
||||
heap[elements] = null;
|
||||
elements--;
|
||||
if (elements+DEFAULT_SIZE/2 <= (heap.length/4)) {
|
||||
TimerTask new_heap[] = new TimerTask[heap.length/2];
|
||||
System.arraycopy(heap, 0, new_heap, 0, elements+1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a task to the queue and puts it at the correct place
|
||||
* in the heap.
|
||||
*/
|
||||
public synchronized void enqueue(TimerTask task) {
|
||||
|
||||
// Check if it is legal to add another element
|
||||
if (heap == null) {
|
||||
throw new IllegalStateException
|
||||
("cannot enqueue when stop() has been called on queue");
|
||||
}
|
||||
|
||||
heap[0] = task; // sentinel
|
||||
add(task); // put the new task at the end
|
||||
// Now push the task up in the heap until it has reached its place
|
||||
int child = elements;
|
||||
int parent = child / 2;
|
||||
while (heap[parent].scheduled > task.scheduled) {
|
||||
heap[child] = heap[parent];
|
||||
child = parent;
|
||||
parent = child / 2;
|
||||
}
|
||||
// This is the correct place for the new task
|
||||
heap[child] = task;
|
||||
heap[0] = null; // clear sentinel
|
||||
// Maybe sched() is waiting for a new element
|
||||
this.notify();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the top element of the queue.
|
||||
* Can return null when no task is in the queue.
|
||||
*/
|
||||
private TimerTask top() {
|
||||
if (elements == 0) {
|
||||
return null;
|
||||
} else {
|
||||
return heap[1];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the top task in the Queue.
|
||||
* Removes the element from the heap and reorders the heap first.
|
||||
* Can return null when there is nothing in the queue.
|
||||
*/
|
||||
public synchronized TimerTask serve() {
|
||||
// The task to return
|
||||
TimerTask task = null;
|
||||
|
||||
while (task == null) {
|
||||
// Get the next task
|
||||
task = top();
|
||||
|
||||
// return null when asked to stop
|
||||
// or if asked to return null when the queue is empty
|
||||
if ((heap == null) || (task == null && nullOnEmpty)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Do we have a task?
|
||||
if (task != null) {
|
||||
// The time to wait until the task should be served
|
||||
long time = task.scheduled-System.currentTimeMillis();
|
||||
if (time > 0) {
|
||||
// This task should not yet be served
|
||||
// So wait until this task is ready
|
||||
// or something else happens to the queue
|
||||
task = null; // set to null to make sure we call top()
|
||||
try {
|
||||
this.wait(time);
|
||||
} catch (InterruptedException _) {}
|
||||
}
|
||||
} else {
|
||||
// wait until a task is added
|
||||
// or something else happens to the queue
|
||||
try {
|
||||
this.wait();
|
||||
} catch (InterruptedException _) {}
|
||||
}
|
||||
}
|
||||
|
||||
// reconstruct the heap
|
||||
TimerTask lastTask = heap[elements];
|
||||
remove();
|
||||
|
||||
// drop lastTask at the beginning and move it down the heap
|
||||
int parent = 1;
|
||||
int child = 2;
|
||||
heap[1] = lastTask;
|
||||
while(child <= elements) {
|
||||
if (child < elements) {
|
||||
if (heap[child].scheduled > heap[child+1].scheduled) {
|
||||
child++;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastTask.scheduled <= heap[child].scheduled)
|
||||
break; // found the correct place (the parent) - done
|
||||
|
||||
heap[parent] = heap[child];
|
||||
parent = child;
|
||||
child = parent*2;
|
||||
}
|
||||
|
||||
// this is the correct new place for the lastTask
|
||||
heap[parent] = lastTask;
|
||||
|
||||
// return the task
|
||||
return task;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* When nullOnEmpty is true the serve() method will return null when
|
||||
* there are no tasks in the queue, otherwise it will wait until
|
||||
* a new element is added to the queue. It is used to indicate to
|
||||
* the scheduler that no new tasks will ever be added to the queue.
|
||||
*/
|
||||
public synchronized void setNullOnEmpty(boolean nullOnEmpty) {
|
||||
this.nullOnEmpty = nullOnEmpty;
|
||||
this.notify();
|
||||
}
|
||||
|
||||
/**
|
||||
* When this method is called the current and all future calls to
|
||||
* serve() will return null. It is used to indicate to the Scheduler
|
||||
* that it should stop executing since no more tasks will come.
|
||||
*/
|
||||
public synchronized void stop() {
|
||||
this.heap = null;
|
||||
this.notify();
|
||||
}
|
||||
|
||||
} // TaskQueue
|
||||
private TimerTask heap[];
|
||||
|
||||
/**
|
||||
* The scheduler that executes all the tasks on a particular TaskQueue,
|
||||
* reschedules any repeating tasks and that waits when no task has to be
|
||||
* executed immediatly. Stops running when canceled or when the parent
|
||||
* Timer has been finalized and no more tasks have to be executed.
|
||||
* The actual number of elements in the heap
|
||||
* Can be less then heap.length.
|
||||
* Note that heap[0] is used as a sentinel.
|
||||
*/
|
||||
private static final class Scheduler implements Runnable {
|
||||
private int elements;
|
||||
|
||||
// The priority queue containing all the TimerTasks.
|
||||
private TaskQueue queue;
|
||||
/**
|
||||
* Creates a TaskQueue of default size without any elements in it.
|
||||
*/
|
||||
public TaskQueue()
|
||||
{
|
||||
heap = new TimerTask[DEFAULT_SIZE];
|
||||
elements = 0;
|
||||
nullOnEmpty = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Scheduler that will schedule the tasks on the
|
||||
* given TaskQueue.
|
||||
*/
|
||||
public Scheduler(TaskQueue queue) {
|
||||
this.queue = queue;
|
||||
}
|
||||
/**
|
||||
* Adds a TimerTask at the end of the heap.
|
||||
* Grows the heap if necessary by doubling the heap in size.
|
||||
*/
|
||||
private void add(TimerTask task)
|
||||
{
|
||||
elements++;
|
||||
if (elements == heap.length)
|
||||
{
|
||||
TimerTask new_heap[] = new TimerTask[heap.length * 2];
|
||||
System.arraycopy(heap, 0, new_heap, 0, heap.length);
|
||||
heap = new_heap;
|
||||
}
|
||||
heap[elements] = task;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
TimerTask task;
|
||||
while((task = queue.serve()) != null) {
|
||||
// If this task has not been canceled
|
||||
if (task.scheduled >= 0) {
|
||||
/**
|
||||
* Removes the last element from the heap.
|
||||
* Shrinks the heap in half if
|
||||
* elements+DEFAULT_SIZE/2 <= heap.length/4.
|
||||
*/
|
||||
private void remove()
|
||||
{
|
||||
// clear the entry first
|
||||
heap[elements] = null;
|
||||
elements--;
|
||||
if (elements + DEFAULT_SIZE / 2 <= (heap.length / 4))
|
||||
{
|
||||
TimerTask new_heap[] = new TimerTask[heap.length / 2];
|
||||
System.arraycopy(heap, 0, new_heap, 0, elements + 1);
|
||||
heap = new_heap;
|
||||
}
|
||||
}
|
||||
|
||||
// Mark execution time
|
||||
task.lastExecutionTime = task.scheduled;
|
||||
/**
|
||||
* Adds a task to the queue and puts it at the correct place
|
||||
* in the heap.
|
||||
*/
|
||||
public synchronized void enqueue(TimerTask task)
|
||||
{
|
||||
// Check if it is legal to add another element
|
||||
if (heap == null)
|
||||
{
|
||||
throw new IllegalStateException
|
||||
("cannot enqueue when stop() has been called on queue");
|
||||
}
|
||||
|
||||
// Repeatable task?
|
||||
if (task.period < 0) {
|
||||
// Last time this task is executed
|
||||
task.scheduled = -1;
|
||||
}
|
||||
heap[0] = task; // sentinel
|
||||
add(task); // put the new task at the end
|
||||
// Now push the task up in the heap until it has reached its place
|
||||
int child = elements;
|
||||
int parent = child / 2;
|
||||
while (heap[parent].scheduled > task.scheduled)
|
||||
{
|
||||
heap[child] = heap[parent];
|
||||
child = parent;
|
||||
parent = child / 2;
|
||||
}
|
||||
// This is the correct place for the new task
|
||||
heap[child] = task;
|
||||
heap[0] = null; // clear sentinel
|
||||
// Maybe sched() is waiting for a new element
|
||||
this.notify();
|
||||
}
|
||||
|
||||
// Run the task
|
||||
try {
|
||||
task.run();
|
||||
} catch (Throwable t) {/* ignore all errors */}
|
||||
}
|
||||
/**
|
||||
* Returns the top element of the queue.
|
||||
* Can return null when no task is in the queue.
|
||||
*/
|
||||
private TimerTask top()
|
||||
{
|
||||
if (elements == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return heap[1];
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate next time and possibly re-enqueue
|
||||
if (task.scheduled >= 0) {
|
||||
if (task.fixed) {
|
||||
task.scheduled += task.period;
|
||||
} else {
|
||||
task.scheduled = task.period +
|
||||
System.currentTimeMillis();
|
||||
}
|
||||
queue.enqueue(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // Scheduler
|
||||
/**
|
||||
* Returns the top task in the Queue.
|
||||
* Removes the element from the heap and reorders the heap first.
|
||||
* Can return null when there is nothing in the queue.
|
||||
*/
|
||||
public synchronized TimerTask serve()
|
||||
{
|
||||
// The task to return
|
||||
TimerTask task = null;
|
||||
|
||||
// Number of Timers created.
|
||||
// Used for creating nice Thread names.
|
||||
private static int nr = 0;
|
||||
while (task == null)
|
||||
{
|
||||
// Get the next task
|
||||
task = top();
|
||||
|
||||
// The queue that all the tasks are put in.
|
||||
// Given to the scheduler
|
||||
// return null when asked to stop
|
||||
// or if asked to return null when the queue is empty
|
||||
if ((heap == null) || (task == null && nullOnEmpty))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Do we have a task?
|
||||
if (task != null)
|
||||
{
|
||||
// The time to wait until the task should be served
|
||||
long time = task.scheduled - System.currentTimeMillis();
|
||||
if (time > 0)
|
||||
{
|
||||
// This task should not yet be served
|
||||
// So wait until this task is ready
|
||||
// or something else happens to the queue
|
||||
task = null; // set to null to make sure we call top()
|
||||
try
|
||||
{
|
||||
this.wait(time);
|
||||
}
|
||||
catch (InterruptedException _)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// wait until a task is added
|
||||
// or something else happens to the queue
|
||||
try
|
||||
{
|
||||
this.wait();
|
||||
}
|
||||
catch (InterruptedException _)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// reconstruct the heap
|
||||
TimerTask lastTask = heap[elements];
|
||||
remove();
|
||||
|
||||
// drop lastTask at the beginning and move it down the heap
|
||||
int parent = 1;
|
||||
int child = 2;
|
||||
heap[1] = lastTask;
|
||||
while (child <= elements)
|
||||
{
|
||||
if (child < elements)
|
||||
{
|
||||
if (heap[child].scheduled > heap[child + 1].scheduled)
|
||||
{
|
||||
child++;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastTask.scheduled <= heap[child].scheduled)
|
||||
break; // found the correct place (the parent) - done
|
||||
|
||||
heap[parent] = heap[child];
|
||||
parent = child;
|
||||
child = parent * 2;
|
||||
}
|
||||
|
||||
// this is the correct new place for the lastTask
|
||||
heap[parent] = lastTask;
|
||||
|
||||
// return the task
|
||||
return task;
|
||||
}
|
||||
|
||||
/**
|
||||
* When nullOnEmpty is true the serve() method will return null when
|
||||
* there are no tasks in the queue, otherwise it will wait until
|
||||
* a new element is added to the queue. It is used to indicate to
|
||||
* the scheduler that no new tasks will ever be added to the queue.
|
||||
*/
|
||||
public synchronized void setNullOnEmpty(boolean nullOnEmpty)
|
||||
{
|
||||
this.nullOnEmpty = nullOnEmpty;
|
||||
this.notify();
|
||||
}
|
||||
|
||||
/**
|
||||
* When this method is called the current and all future calls to
|
||||
* serve() will return null. It is used to indicate to the Scheduler
|
||||
* that it should stop executing since no more tasks will come.
|
||||
*/
|
||||
public synchronized void stop()
|
||||
{
|
||||
this.heap = null;
|
||||
this.notify();
|
||||
}
|
||||
|
||||
} // TaskQueue
|
||||
|
||||
/**
|
||||
* The scheduler that executes all the tasks on a particular TaskQueue,
|
||||
* reschedules any repeating tasks and that waits when no task has to be
|
||||
* executed immediatly. Stops running when canceled or when the parent
|
||||
* Timer has been finalized and no more tasks have to be executed.
|
||||
*/
|
||||
private static final class Scheduler implements Runnable
|
||||
{
|
||||
// The priority queue containing all the TimerTasks.
|
||||
private TaskQueue queue;
|
||||
|
||||
// The Scheduler that does all the real work
|
||||
private Scheduler scheduler;
|
||||
|
||||
// Used to run the scheduler.
|
||||
// Also used to checked if the Thread is still running by calling
|
||||
// thread.isAlive(). Sometimes a Thread is suddenly killed by the system
|
||||
// (if it belonged to an Applet).
|
||||
private Thread thread;
|
||||
|
||||
// When cancelled we don't accept any more TimerTasks.
|
||||
private boolean canceled;
|
||||
|
||||
/**
|
||||
* Creates a new Timer with a non deamon Thread as Scheduler, with normal
|
||||
* priority and a default name.
|
||||
* Creates a new Scheduler that will schedule the tasks on the
|
||||
* given TaskQueue.
|
||||
*/
|
||||
public Timer() {
|
||||
this(false);
|
||||
public Scheduler(TaskQueue queue)
|
||||
{
|
||||
this.queue = queue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Timer with a deamon Thread as scheduler if deamon is true,
|
||||
* with normal priority and a default name.
|
||||
*/
|
||||
public Timer(boolean daemon) {
|
||||
this(daemon, Thread.NORM_PRIORITY);
|
||||
public void run()
|
||||
{
|
||||
TimerTask task;
|
||||
while ((task = queue.serve()) != null)
|
||||
{
|
||||
// If this task has not been canceled
|
||||
if (task.scheduled >= 0)
|
||||
{
|
||||
|
||||
// Mark execution time
|
||||
task.lastExecutionTime = task.scheduled;
|
||||
|
||||
// Repeatable task?
|
||||
if (task.period < 0)
|
||||
{
|
||||
// Last time this task is executed
|
||||
task.scheduled = -1;
|
||||
}
|
||||
|
||||
// Run the task
|
||||
try
|
||||
{
|
||||
task.run();
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
/* ignore all errors */
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate next time and possibly re-enqueue
|
||||
if (task.scheduled >= 0)
|
||||
{
|
||||
if (task.fixed)
|
||||
{
|
||||
task.scheduled += task.period;
|
||||
}
|
||||
else
|
||||
{
|
||||
task.scheduled = task.period + System.currentTimeMillis();
|
||||
}
|
||||
queue.enqueue(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // Scheduler
|
||||
|
||||
/**
|
||||
* Creates a new Timer with a deamon Thread as scheduler if deamon is true,
|
||||
* with the priority given and a default name.
|
||||
*/
|
||||
private Timer(boolean daemon, int priority) {
|
||||
this(daemon, priority, "Timer-" + (++nr));
|
||||
}
|
||||
// Number of Timers created.
|
||||
// Used for creating nice Thread names.
|
||||
private static int nr = 0;
|
||||
|
||||
/**
|
||||
* Creates a new Timer with a deamon Thread as scheduler if deamon is true,
|
||||
* with the priority and name given.E
|
||||
*/
|
||||
private Timer(boolean daemon, int priority, String name) {
|
||||
canceled = false;
|
||||
queue = new TaskQueue();
|
||||
scheduler = new Scheduler(queue);
|
||||
thread = new Thread(scheduler, name);
|
||||
thread.setDaemon(daemon);
|
||||
thread.setPriority(priority);
|
||||
thread.start();
|
||||
}
|
||||
// The queue that all the tasks are put in.
|
||||
// Given to the scheduler
|
||||
private TaskQueue queue;
|
||||
|
||||
/**
|
||||
* Cancels the execution of the scheduler. If a task is executing it will
|
||||
* normally finish execution, but no other tasks will be executed and no
|
||||
* more tasks can be scheduled.
|
||||
*/
|
||||
public void cancel() {
|
||||
canceled = true;
|
||||
queue.stop();
|
||||
}
|
||||
// The Scheduler that does all the real work
|
||||
private Scheduler scheduler;
|
||||
|
||||
/**
|
||||
* Schedules the task at Time time, repeating every period
|
||||
* milliseconds if period is positive and at a fixed rate if fixed is true.
|
||||
*
|
||||
* @exception IllegalArgumentException if time is negative
|
||||
* @exception IllegalStateException if the task was already scheduled or
|
||||
* canceled or this Timer is canceled or the scheduler thread has died
|
||||
*/
|
||||
private void schedule(TimerTask task,
|
||||
long time,
|
||||
long period,
|
||||
boolean fixed) {
|
||||
// Used to run the scheduler.
|
||||
// Also used to checked if the Thread is still running by calling
|
||||
// thread.isAlive(). Sometimes a Thread is suddenly killed by the system
|
||||
// (if it belonged to an Applet).
|
||||
private Thread thread;
|
||||
|
||||
if (time < 0)
|
||||
throw new IllegalArgumentException("negative time");
|
||||
// When cancelled we don't accept any more TimerTasks.
|
||||
private boolean canceled;
|
||||
|
||||
if (task.scheduled == 0 && task.lastExecutionTime == -1) {
|
||||
task.scheduled = time;
|
||||
task.period = period;
|
||||
task.fixed = fixed;
|
||||
} else {
|
||||
throw new IllegalStateException
|
||||
("task was already scheduled or canceled");
|
||||
}
|
||||
/**
|
||||
* Creates a new Timer with a non deamon Thread as Scheduler, with normal
|
||||
* priority and a default name.
|
||||
*/
|
||||
public Timer()
|
||||
{
|
||||
this(false);
|
||||
}
|
||||
|
||||
if (!this.canceled && this.thread != null) {
|
||||
queue.enqueue(task);
|
||||
} else {
|
||||
throw new IllegalStateException
|
||||
("timer was canceled or scheduler thread has died");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Creates a new Timer with a deamon Thread as scheduler if deamon is true,
|
||||
* with normal priority and a default name.
|
||||
*/
|
||||
public Timer(boolean daemon)
|
||||
{
|
||||
this(daemon, Thread.NORM_PRIORITY);
|
||||
}
|
||||
|
||||
private static void positiveDelay(long delay) {
|
||||
if (delay < 0) {
|
||||
throw new IllegalArgumentException("delay is negative");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Creates a new Timer with a deamon Thread as scheduler if deamon is true,
|
||||
* with the priority given and a default name.
|
||||
*/
|
||||
private Timer(boolean daemon, int priority)
|
||||
{
|
||||
this(daemon, priority, "Timer-" + (++nr));
|
||||
}
|
||||
|
||||
private static void positivePeriod(long period) {
|
||||
if (period < 0) {
|
||||
throw new IllegalArgumentException("period is negative");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Creates a new Timer with a deamon Thread as scheduler if deamon is true,
|
||||
* with the priority and name given.E
|
||||
*/
|
||||
private Timer(boolean daemon, int priority, String name)
|
||||
{
|
||||
canceled = false;
|
||||
queue = new TaskQueue();
|
||||
scheduler = new Scheduler(queue);
|
||||
thread = new Thread(scheduler, name);
|
||||
thread.setDaemon(daemon);
|
||||
thread.setPriority(priority);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules the task at the specified data for one time execution.
|
||||
*
|
||||
* @exception IllegalArgumentException if date.getTime() is negative
|
||||
* @exception IllegalStateException if the task was already scheduled or
|
||||
* canceled or this Timer is canceled or the scheduler thread has died
|
||||
*/
|
||||
public void schedule(TimerTask task, Date date) {
|
||||
long time = date.getTime();
|
||||
schedule(task, time, -1, false);
|
||||
}
|
||||
/**
|
||||
* Cancels the execution of the scheduler. If a task is executing it will
|
||||
* normally finish execution, but no other tasks will be executed and no
|
||||
* more tasks can be scheduled.
|
||||
*/
|
||||
public void cancel()
|
||||
{
|
||||
canceled = true;
|
||||
queue.stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules the task at the specified date and reschedules the task every
|
||||
* period milliseconds after the last execution of the task finishes until
|
||||
* this timer or the task is canceled.
|
||||
*
|
||||
* @exception IllegalArgumentException if period or date.getTime() is
|
||||
* negative
|
||||
* @exception IllegalStateException if the task was already scheduled or
|
||||
* canceled or this Timer is canceled or the scheduler thread has died
|
||||
*/
|
||||
public void schedule(TimerTask task, Date date, long period) {
|
||||
positivePeriod(period);
|
||||
long time = date.getTime();
|
||||
schedule(task, time, period, false);
|
||||
}
|
||||
/**
|
||||
* Schedules the task at Time time, repeating every period
|
||||
* milliseconds if period is positive and at a fixed rate if fixed is true.
|
||||
*
|
||||
* @exception IllegalArgumentException if time is negative
|
||||
* @exception IllegalStateException if the task was already scheduled or
|
||||
* canceled or this Timer is canceled or the scheduler thread has died
|
||||
*/
|
||||
private void schedule(TimerTask task, long time, long period, boolean fixed)
|
||||
{
|
||||
if (time < 0)
|
||||
throw new IllegalArgumentException("negative time");
|
||||
|
||||
/**
|
||||
* Schedules the task after the specified delay milliseconds for one time
|
||||
* execution.
|
||||
*
|
||||
* @exception IllegalArgumentException if delay or
|
||||
* System.currentTimeMillis + delay is negative
|
||||
* @exception IllegalStateException if the task was already scheduled or
|
||||
* canceled or this Timer is canceled or the scheduler thread has died
|
||||
*/
|
||||
public void schedule(TimerTask task, long delay) {
|
||||
positiveDelay(delay);
|
||||
long time = System.currentTimeMillis() + delay;
|
||||
schedule(task, time, -1, false);
|
||||
}
|
||||
if (task.scheduled == 0 && task.lastExecutionTime == -1)
|
||||
{
|
||||
task.scheduled = time;
|
||||
task.period = period;
|
||||
task.fixed = fixed;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalStateException
|
||||
("task was already scheduled or canceled");
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules the task after the delay milliseconds and reschedules the
|
||||
* task every period milliseconds after the last execution of the task
|
||||
* finishes until this timer or the task is canceled.
|
||||
*
|
||||
* @exception IllegalArgumentException if delay or period is negative
|
||||
* @exception IllegalStateException if the task was already scheduled or
|
||||
* canceled or this Timer is canceled or the scheduler thread has died
|
||||
*/
|
||||
public void schedule(TimerTask task, long delay, long period) {
|
||||
positiveDelay(delay);
|
||||
positivePeriod(period);
|
||||
long time = System.currentTimeMillis() + delay;
|
||||
schedule(task, time, period, false);
|
||||
}
|
||||
if (!this.canceled && this.thread != null)
|
||||
{
|
||||
queue.enqueue(task);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalStateException
|
||||
("timer was canceled or scheduler thread has died");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules the task at the specified date and reschedules the task at a
|
||||
* fixed rate every period milliseconds until this timer or the task is
|
||||
* canceled.
|
||||
*
|
||||
* @exception IllegalArgumentException if period or date.getTime() is
|
||||
* negative
|
||||
* @exception IllegalStateException if the task was already scheduled or
|
||||
* canceled or this Timer is canceled or the scheduler thread has died
|
||||
*/
|
||||
public void scheduleAtFixedRate(TimerTask task, Date date, long period) {
|
||||
positivePeriod(period);
|
||||
long time = date.getTime();
|
||||
schedule(task, time, period, true);
|
||||
}
|
||||
private static void positiveDelay(long delay)
|
||||
{
|
||||
if (delay < 0)
|
||||
{
|
||||
throw new IllegalArgumentException("delay is negative");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules the task after the delay milliseconds and reschedules the task
|
||||
* at a fixed rate every period milliseconds until this timer or the task
|
||||
* is canceled.
|
||||
*
|
||||
* @exception IllegalArgumentException if delay or
|
||||
* System.currentTimeMillis + delay is negative
|
||||
* @exception IllegalStateException if the task was already scheduled or
|
||||
* canceled or this Timer is canceled or the scheduler thread has died
|
||||
*/
|
||||
public void scheduleAtFixedRate(TimerTask task, long delay, long period) {
|
||||
positiveDelay(delay);
|
||||
positivePeriod(period);
|
||||
long time = System.currentTimeMillis() + delay;
|
||||
schedule(task, time, period, true);
|
||||
}
|
||||
private static void positivePeriod(long period)
|
||||
{
|
||||
if (period < 0)
|
||||
{
|
||||
throw new IllegalArgumentException("period is negative");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the scheduler that the Timer task died
|
||||
* so there will be no more new tasks scheduled.
|
||||
*/
|
||||
protected void finalize() {
|
||||
queue.setNullOnEmpty(true);
|
||||
}
|
||||
/**
|
||||
* Schedules the task at the specified data for one time execution.
|
||||
*
|
||||
* @exception IllegalArgumentException if date.getTime() is negative
|
||||
* @exception IllegalStateException if the task was already scheduled or
|
||||
* canceled or this Timer is canceled or the scheduler thread has died
|
||||
*/
|
||||
public void schedule(TimerTask task, Date date)
|
||||
{
|
||||
long time = date.getTime();
|
||||
schedule(task, time, -1, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules the task at the specified date and reschedules the task every
|
||||
* period milliseconds after the last execution of the task finishes until
|
||||
* this timer or the task is canceled.
|
||||
*
|
||||
* @exception IllegalArgumentException if period or date.getTime() is
|
||||
* negative
|
||||
* @exception IllegalStateException if the task was already scheduled or
|
||||
* canceled or this Timer is canceled or the scheduler thread has died
|
||||
*/
|
||||
public void schedule(TimerTask task, Date date, long period)
|
||||
{
|
||||
positivePeriod(period);
|
||||
long time = date.getTime();
|
||||
schedule(task, time, period, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules the task after the specified delay milliseconds for one time
|
||||
* execution.
|
||||
*
|
||||
* @exception IllegalArgumentException if delay or
|
||||
* System.currentTimeMillis + delay is negative
|
||||
* @exception IllegalStateException if the task was already scheduled or
|
||||
* canceled or this Timer is canceled or the scheduler thread has died
|
||||
*/
|
||||
public void schedule(TimerTask task, long delay)
|
||||
{
|
||||
positiveDelay(delay);
|
||||
long time = System.currentTimeMillis() + delay;
|
||||
schedule(task, time, -1, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules the task after the delay milliseconds and reschedules the
|
||||
* task every period milliseconds after the last execution of the task
|
||||
* finishes until this timer or the task is canceled.
|
||||
*
|
||||
* @exception IllegalArgumentException if delay or period is negative
|
||||
* @exception IllegalStateException if the task was already scheduled or
|
||||
* canceled or this Timer is canceled or the scheduler thread has died
|
||||
*/
|
||||
public void schedule(TimerTask task, long delay, long period)
|
||||
{
|
||||
positiveDelay(delay);
|
||||
positivePeriod(period);
|
||||
long time = System.currentTimeMillis() + delay;
|
||||
schedule(task, time, period, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules the task at the specified date and reschedules the task at a
|
||||
* fixed rate every period milliseconds until this timer or the task is
|
||||
* canceled.
|
||||
*
|
||||
* @exception IllegalArgumentException if period or date.getTime() is
|
||||
* negative
|
||||
* @exception IllegalStateException if the task was already scheduled or
|
||||
* canceled or this Timer is canceled or the scheduler thread has died
|
||||
*/
|
||||
public void scheduleAtFixedRate(TimerTask task, Date date, long period)
|
||||
{
|
||||
positivePeriod(period);
|
||||
long time = date.getTime();
|
||||
schedule(task, time, period, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules the task after the delay milliseconds and reschedules the task
|
||||
* at a fixed rate every period milliseconds until this timer or the task
|
||||
* is canceled.
|
||||
*
|
||||
* @exception IllegalArgumentException if delay or
|
||||
* System.currentTimeMillis + delay is negative
|
||||
* @exception IllegalStateException if the task was already scheduled or
|
||||
* canceled or this Timer is canceled or the scheduler thread has died
|
||||
*/
|
||||
public void scheduleAtFixedRate(TimerTask task, long delay, long period)
|
||||
{
|
||||
positiveDelay(delay);
|
||||
positivePeriod(period);
|
||||
long time = System.currentTimeMillis() + delay;
|
||||
schedule(task, time, period, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the scheduler that the Timer task died
|
||||
* so there will be no more new tasks scheduled.
|
||||
*/
|
||||
protected void finalize()
|
||||
{
|
||||
queue.setNullOnEmpty(true);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue