All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.jackrabbit.util.Timer Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.jackrabbit.util;

import java.util.TimerTask;

/**
 * Timer wraps the standard Java {@link java.util.Timer} class
 * and implements a guaranteed shutdown of the background thread running
 * in the Timer instance after a certain {@link #IDLE_TIME}.
 */
public class Timer {

    /**
     * Idle time in milliseconds. When a timer instance is idle for this amount
     * of time the underlying timer is canceled.
     */
    static final int IDLE_TIME = 3 * 1000;

    /**
     * The interval at which the idle checker task runs.
     */
    static final int CHECKER_INTERVAL = 1000;

    /**
     * The timer implementation we us internally.
     */
    private java.util.Timer delegatee;

    /**
     * Indicates whether the timer thread should run as deamon.
     */
    private final boolean runAsDeamon;

    /**
     * The number of currently scheduled tasks. If this value drops to zero
     * the internal {@link java.util.Timer} instance is canceled. Whenever
     * this value increases from zero to one a new {@link java.util.Timer}
     * instance is created and started.
     */
    private int numScheduledTasks = 0;

    /**
     * The time when the last task was scheduled.
     */
    private long lastTaskScheduled;

    /**
     * Creates a new Timer instance.
     *
     * @param isDeamon if true the background thread wil run as
     *                 deamon.
     */
    public Timer(boolean isDeamon) {
        runAsDeamon = isDeamon;
    }

    /**
     * Schedules the specified task for repeated fixed-delay execution,
     * beginning after the specified delay.  Subsequent executions take place
     * at approximately regular intervals separated by the specified period.
     *
     * @param task   task to be scheduled.
     * @param delay  delay in milliseconds before task is to be executed.
     * @param period time in milliseconds between successive task executions.
     * @throws IllegalArgumentException if delay is negative, or
     *         delay + System.currentTimeMillis() is negative.
     * @throws IllegalStateException if task was already scheduled or
     *         cancelled, timer was cancelled, or timer thread terminated.
     * @see java.util.Timer#schedule(java.util.TimerTask, long, long)
     */
    public void schedule(Task task, long delay, long period) {
        if (delay < 0)
            throw new IllegalArgumentException("Negative delay.");
        if (period <= 0)
            throw new IllegalArgumentException("Non-positive period.");
        synchronized (this) {
            if (delegatee == null) {
                delegatee = new java.util.Timer(runAsDeamon);
                // run idle checker every second
                Task idleChecker = new IdleCheckerTask();
                idleChecker.setTimer(this);
                delegatee.schedule(idleChecker, IDLE_TIME, CHECKER_INTERVAL);
            }
            delegatee.schedule(task, delay, period);
            task.setTimer(this);
            numScheduledTasks++;
            lastTaskScheduled = System.currentTimeMillis();
        }
    }

    /**
     * Terminates this timer, discarding any currently scheduled tasks.
     * Does not interfere with a currently executing task (if it exists).
     * Once a timer has been terminated, its execution thread terminates
     * gracefully, and no more tasks may be scheduled on it.
     *
     * 

Note that calling this method from within the run method of a * timer task that was invoked by this timer absolutely guarantees that * the ongoing task execution is the last task execution that will ever * be performed by this timer. * *

This method may be called repeatedly; the second and subsequent * calls have no effect. */ public void cancel() { synchronized (this) { if (delegatee != null) { delegatee.cancel(); numScheduledTasks = 0; delegatee = null; } } } /** * @return true if this timer has a running backround thread * for scheduled tasks. This method is only for test purposes. */ boolean isRunning() { synchronized (this) { return delegatee != null; } } /** * Notifies this Timer that a task has been canceled. */ private void taskCanceled() { synchronized (this) { --numScheduledTasks; } } /** * Extends the TimerTask with callback hooks to this * Timer implementation. */ public static abstract class Task extends TimerTask { /** * The Timer instance where this Task is * scheduled on. */ private Timer timer; /** * Sets the timer instance where this task is scheduled on. * @param timer the timer instance. */ private void setTimer(Timer timer) { this.timer = timer; } /** * {@inheritDoc} */ public final boolean cancel() { if (timer != null) { timer.taskCanceled(); timer = null; } return super.cancel(); } } /** * Checks if the enclosing timer had been idle for at least * {@link Timer#IDLE_TIME} and cancels it in that case. */ private class IdleCheckerTask extends Task { public void run() { synchronized (Timer.this) { if (numScheduledTasks == 0 && System.currentTimeMillis() > lastTaskScheduled + IDLE_TIME) { if (delegatee != null) { delegatee.cancel(); delegatee = null; } } } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy