📄 hsqltimer.java
字号:
/* Copyright (c) 2001-2008, The HSQL Development Group * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the HSQL Development Group nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG, * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */package org.hsqldb.lib;import java.util.Date;/** * Facility to schedule tasks for future execution in a background thread. <p> * * Tasks may be scheduled for one-time execution or for repeated execution at * regular intervals, using either fixed rate or fixed delay policy. <p> * * This class is a JDK 1.1 compatible implementation required by HSQLDB both * because the java.util.Timer class is available only in JDK 1.3+ and because * java.util.Timer starves least recently added tasks under high load and * fixed rate scheduling, especially when the average actual task duration is * greater than the average requested task periodicity. <p> * * An additional (minor) advantage over java.util.Timer is that this class does * not retain a live background thread during periods when the task queue is * empty. * @author boucherb@users * @version 1.8.0.10 * @since 1.7.2 */public final class HsqlTimer implements ObjectComparator, ThreadFactory { /** The priority queue for the scheduled tasks. */ protected final TaskQueue taskQueue = new TaskQueue(16, (ObjectComparator) this); /** The inner runnable that executes tasks in the background thread. */ protected final TaskRunner taskRunner = new TaskRunner(); /** The background thread. */ protected Thread taskRunnerThread; /** The factory that procduces the background threads. */ protected final ThreadFactory threadFactory; /** * Whether this timer should disallow all further processing. * * Once set true, stays true forever. */ protected volatile boolean isShutdown; /** * Constructs a new HsqlTimer using the default thread factory * implementation. */ public HsqlTimer() { this(null); } /** * Constructs a new HsqlTimer. * * Uses the specified thread factory implementation. * * @param threadFactory the ThreadFactory used to produce this timer's * background threads. If null, the default implementation supplied * by this class will be used. */ public HsqlTimer(final ThreadFactory threadFactory) { this.threadFactory = (threadFactory == null) ? this : threadFactory; } /** * Required to back the priority queue for scheduled tasks. * * @param a the first Task * @param b the second Task * @return 0 if equal, < 0 if a < b, > 0 if a > b */ public int compare(final Object a, final Object b) { final long awhen = ((Task) (a)).getNextScheduled(); final long bwhen = ((Task) (b)).getNextScheduled(); return (awhen < bwhen) ? -1 : (awhen == bwhen) ? 0 : 1; } /** * Default ThreadFactory implementation. <p> * * Contructs a new Thread from the designated runnable, sets its * name to "HSQLDB Timer @" + Integer.toHexString(hashCode()), * and sets it as a daemon thread. <p> * * @param runnable used to construct the new Thread. * @return a new Thread constructed from the designated runnable. */ public Thread newThread(final Runnable runnable) { final Thread thread = new Thread(runnable); thread.setName("HSQLDB Timer @" + Integer.toHexString(hashCode())); thread.setDaemon(true); return thread; } /** * Retrieves the background execution thread. <p> * * null is returned if there is no such thread. <p> * * @return the current background thread (may be null) */ public synchronized Thread getThread() { return this.taskRunnerThread; } /** * (Re)starts background processing of the task queue. * * @throws IllegalStateException if this timer is shut down. * @see #shutdown() * @see #shutdownImmediately() */ public synchronized void restart() throws IllegalStateException { if (this.isShutdown) { throw new IllegalStateException("isShutdown==true"); } else if (this.taskRunnerThread == null) { this.taskRunnerThread = this.threadFactory.newThread(this.taskRunner); this.taskRunnerThread.start(); } else { this.taskQueue.unpark(); } } /** * Causes the specified Runnable to be executed once in the background * after the specified delay. * * @param delay in milliseconds * @param runnable the Runnable to execute. * @return opaque reference to the internal task * @throws IllegalArgumentException if runnable is null */ public Object scheduleAfter(final long delay, final Runnable runnable) throws IllegalArgumentException { if (runnable == null) { throw new IllegalArgumentException("runnable == null"); } return this.addTask(now() + delay, runnable, 0, false); } /** * Causes the specified Runnable to be executed once in the background * at the specified time. * * @param date time at which to execute the specified Runnable * @param runnable the Runnable to execute. * @return opaque reference to the internal task * @throws IllegalArgumentException if date or runnable is null */ public Object scheduleAt(final Date date, final Runnable runnable) throws IllegalArgumentException { if (date == null) { throw new IllegalArgumentException("date == null"); } else if (runnable == null) { throw new IllegalArgumentException("runnable == null"); } return this.addTask(date.getTime(), runnable, 0, false); } /** * Causes the specified Runnable to be executed periodically in the * background, starting at the specified time. * * @return opaque reference to the internal task * @param period the cycle period * @param relative if true, fixed rate sheduling else fixed delay scheduling * @param date time at which to execute the specified Runnable * @param runnable the Runnable to execute * @throws IllegalArgumentException if date or runnable is null, or * period is <= 0 */ public Object schedulePeriodicallyAt(final Date date, final long period, final Runnable runnable, final boolean relative) throws IllegalArgumentException { if (date == null) { throw new IllegalArgumentException("date == null"); } else if (period <= 0) { throw new IllegalArgumentException("period <= 0"); } else if (runnable == null) { throw new IllegalArgumentException("runnable == null"); } return addTask(date.getTime(), runnable, period, relative); } /** * Causes the specified Runnable to be executed periodically in the * background, starting after the specified delay. * * @return opaque reference to the internal task * @param period the cycle period * @param relative if true, fixed rate sheduling else fixed delay scheduling * @param delay in milliseconds * @param runnable the Runnable to execute. * @throws IllegalArgumentException if runnable is null or period is <= 0 */ public Object schedulePeriodicallyAfter(final long delay, final long period, final Runnable runnable, final boolean relative) throws IllegalArgumentException { if (period <= 0) { throw new IllegalArgumentException("period <= 0"); } else if (runnable == null) { throw new IllegalArgumentException("runnable == null"); } return addTask(now() + delay, runnable, period, relative); } /** * Shuts down this timer after the current task (if any) completes. <p> * * After this call, the timer has permanently entered the shutdown state; * attempting to schedule any new task or directly restart this timer will * result in an IllegalStateException. <p> * */ public synchronized void shutdown() { if (!this.isShutdown) { this.isShutdown = true; this.taskQueue.cancelAllTasks(); } } /** for compatiblity with previous version */ public synchronized void shutDown() { shutdown(); } /** * Shuts down this timer immediately, interrupting the wait state associated * with the current head of the task queue or the wait state internal to * the currently executing task, if any such state is currently in effect. * * After this call, the timer has permanently entered the shutdown state; * attempting to schedule any new task or directly restart this timer will * result in an IllegalStateException. <p> * * <b>Note:</b> If the integrity of work performed by a scheduled task * may be adversely affected by an unplanned interruption, it is the * responsibility of the task's implementation to deal correctly with the * possibility that this method is called while such work is in progress, * for instance by catching the InterruptedException, completing the work, * and then rethrowing the exception. */ public synchronized void shutdownImmediately() { if (!this.isShutdown) { final Thread runner = this.taskRunnerThread; this.isShutdown = true; if (runner != null && runner.isAlive()) { runner.interrupt(); } this.taskQueue.cancelAllTasks(); } } /** * Causes the task referenced by the supplied argument to be cancelled. * If the referenced task is currently executing, it will continue until * finished but will not be rescheduled. * * @param task a task reference */ public static void cancel(final Object task) { if (task instanceof Task) { ((Task) task).cancel(); } } /** * Retrieves whether the specified argument references a cancelled task. * * @param task a task reference * @return true if referenced task is cancelled */ public static boolean isCancelled(final Object task) { return (task instanceof Task) ? ((Task) task).isCancelled() : true; } /** * Retrieves whether the specified argument references a task scheduled * periodically using fixed rate scheduling. * * @param task a task reference * @return true if the task is scheduled at a fixed rate */ public static boolean isFixedRate(final Object task) { if (task instanceof Task) { final Task ltask = (Task) task; return (ltask.relative && ltask.period > 0); } else { return false; } } /** * Retrieves whether the specified argument references a task scheduled * periodically using fixed delay scheduling. * * @param task a task reference * @return true if the reference is scheduled using a fixed delay */ public static boolean isFixedDelay(final Object task) { if (task instanceof Task) { final Task ltask = (Task) task; return (!ltask.relative && ltask.period > 0); } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -