Your own timer
/* * Copyright (c) 1998-2002 Carnegie Mellon University. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. 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. * * THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND * ANY EXPRESSED 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 CARNEGIE MELLON UNIVERSITY * NOR ITS EMPLOYEES 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. * */ import java.util.Vector; public class Timer { int interval; boolean periodic; boolean isExpired = false; static TimerManager manager = new TimerManager (); long deadline; Timer next, prev; public Timer () { } public void set (int msecDelay, boolean periodic) { interval = msecDelay; this.periodic = periodic; isExpired = false; if (!manager.isAlive ()) { System.err.println ("TimerManager: restarting"); manager = new TimerManager (); } manager.register (this, System.currentTimeMillis () + msecDelay); } public int getInterval () { return interval; } public boolean getPeriodic () { return periodic; } public void cancel () { manager.delete (this); } protected void alarm () { } public boolean expired () { return isExpired; } /* public static void main (String[] args) { for (int i=0; i<args.length; ++i) { boolean periodic = (args[i].charAt (0) == 'p'); if (periodic) args[i] = args[i].substring (1); new TestTimer (args[i], Integer.parseInt (args[i]), periodic); } while (true) Thread.yield (); } */ } class TimerManager extends Thread { Timer first, last; /* static ThreadGroup rootThreadGroup; static { rootThreadGroup = Thread.currentThread().getThreadGroup(); while (rootThreadGroup.getParent() != null) rootThreadGroup = rootThreadGroup.getParent(); } */ public TimerManager () { super (/* rootThreadGroup, */ "Timer Manager"); setDaemon (true); start (); } public synchronized void register (Timer t, long deadline) { t.deadline = deadline; delete (t); // just in case it's already registered //System.err.println ("TimerManager: set " + t + " to go off at " + deadline); insertion: { for (Timer u = first; u != null; u = u.next) { if (t.deadline < u.deadline) { if (u.prev != null) u.prev.next = t; else first = t; t.prev = u.prev; t.next = u; u.prev = t; break insertion; } } if (last != null) { last.next = t; t.prev = last; t.next = null; last = t; } else { first = last = t; } } //System.err.println ("TimerManager: waking up background thread"); notifyAll (); } public synchronized void delete (Timer t) { if (t.next != null) t.next.prev = t.prev; if (t.prev != null) t.prev.next = t.next; if (t == last) last = t.prev; if (t == first) first = t.next; t.next = null; t.prev = null; } static final int FOREVER = 60000; // wake up at least every 60 seconds public synchronized void run () { while (true) { try { //System.err.println ("TimerManager: awake"); if (first == null) { //System.err.println ("TimerManager: waiting forever"); wait (FOREVER); //System.err.println ("TimerManager: woke up"); } else { Timer t = first; long now = System.currentTimeMillis (); if (t.deadline <= now) { // System.err.println ("TimerManager: timer " + t + " just went off at " + now); try { t.isExpired = true; t.alarm (); } catch (Throwable e) { if (e instanceof ThreadDeath) throw (ThreadDeath)e; else e.printStackTrace (); } if (t.periodic) { register (t, now + t.interval); } else { delete (t); } } else { //System.err.println ("TimerManager: waiting for " + (t.deadline - now) + " msec"); wait (t.deadline - now); //System.err.println ("TimerManager: woke up"); } } } catch (InterruptedException e) {} } } } /* class TestTimer extends Timer { String message; public TestTimer (String message, int millisec, boolean periodic) { this.message = message; set (millisec, periodic); } public void alarm () { System.out.println (message); } } */