📄 timer.java
字号:
/* Timer.java -- Timer that runs TimerTasks at a later time. Copyright (C) 2000, 2001 Free Software Foundation, Inc.This file is part of GNU Classpath.GNU Classpath is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe 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, butWITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNUGeneral Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU Classpath; see the file COPYING. If not, write to theFree Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307 USA.Linking this library statically or dynamically with other modules ismaking a combined work based on this library. Thus, the terms andconditions of the GNU General Public License cover the wholecombination.As a special exception, the copyright holders of this library give youpermission to link this library with independent modules to produce anexecutable, regardless of the license terms of these independentmodules, and to copy and distribute the resulting executable underterms of your choice, provided that you also meet, for each linkedindependent module, the terms and conditions of the license of thatmodule. An independent module is a module which is not derived fromor based on this library. If you modify this library, you may extendthis exception to your version of the library, but you are notobligated to do so. If you do not wish to do so, delete thisexception statement from your version. */package java.util;/** * Timer that can run TimerTasks at a later time. * TimerTasks can be scheduled for one time execution at some time in the * future. They can be scheduled to be rescheduled at a time period after the * task was last executed. Or they can be scheduled to be executed repeatedly * at a fixed rate. * <p> * The normal scheduling will result in a more or less even delay in time * between successive executions, but the executions could drift in time if * the task (or other tasks) takes a long time to execute. Fixed delay * scheduling guarantees more or less that the task will be executed at a * specific time, but if there is ever a delay in execution then the period * between successive executions will be shorter. The first method of * repeated scheduling is preferred for repeated tasks in response to user * interaction, the second method of repeated scheduling is preferred for tasks * that act like alarms. * <p> * The Timer keeps a binary heap as a task priority queue which means that * scheduling and serving of a task in a queue of n tasks costs O(log n). * * @see TimerTask * @since 1.3 * @author Mark Wielaard (mark@klomp.org) */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; /** Whether 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); heap = new_heap; } } /** * 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.elements = 0; 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -