⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 timeout.java

📁 java开源的企业总线.xmlBlaster
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------------ Name:      Timeout.java Project:   xmlBlaster.org Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file Comment:   Allows you be called back after a given delay. ------------------------------------------------------------------------------*/package org.xmlBlaster.util;import java.util.TreeMap;import java.util.NoSuchElementException;import org.xmlBlaster.util.def.ErrorCode;/** * Allows you be called back after a given delay. * <p /> * Note that this class should be called Timer, but with JDK 1.3 there will be a * java.util.Timer. * <p /> * There is a single background thread that is used to execute the * I_Timeout.timeout() callback. Timer callbacks should complete quickly. If a * timeout() takes excessive time to complete, it "hogs" the timer's task * execution thread. This can, in turn, delay the execution of subsequent tasks, * which may "bunch up" and execute in rapid succession when (and if) the * offending task finally completes. * <p /> * This singleton is thread-safe. * <p /> * This class does not offer real-time guarantees, but usually notifies you * within ~ 20 milliseconds of the scheduled time. * <p /> * Adding or removing a timer is good performing, also when huge amounts of * timers (> 1000) are used.<br /> * Feeding of 10000: 10362 adds/sec and all updates came in 942 millis (600MHz * Linux PC with Sun JDK 1.3.1) * * <p /> * TODO: Use a thread pool to dispatch the timeout callbacks. * <p /> * Example:<br /> *  * <pre> *  public class MyClass implements I_Timeout { *    ... *    Timeout timeout = new Timeout(&quot;TestTimer&quot;); *    Timestamp timeoutHandle = timeout.addTimeoutListener(this, 4000L, &quot;myTimeout&quot;); *    ... *    public void timeout(Object userData) { *       // userData contains String &quot;myTimeout&quot; *       System.out.println(&quot;Timeout happened&quot;); *       ... *       // If you want to activate the timer again: *       timeoutHandle = timeout.addTimeoutListener(this, 4000L, &quot;myTimeout&quot;); *    } *    ... *    // if you want to refresh the timer: *    timeoutHandle = timeout.refreshTimeoutListener(timeoutHandle, 1500L); *    ... *  } * </pre> *  * Or a short form: *  * <pre> * Timeout timeout = new Timeout(&quot;TestTimer&quot;); *  * Timestamp timeoutHandle = timeout.addTimeoutListener(new I_Timeout() { *    public void timeout(Object userData) { *       System.out.println(&quot;Timeout happened&quot;); *       System.exit(0); *    } * }, 2000L, null); * </pre> *  * JDK 1.2 or higher only. *  * @author xmlBlaster@marcelruff.info * @see org.xmlBlaster.test.classtest.TimeoutTest */public class Timeout extends Thread {   /** Name for logging output */   private static String ME = "Timeout";   /** Sorted map */   private TreeMap map = null;   /** Start/Stop the Timeout manager thread */   private boolean running = true;   /** On creation wait until thread started */   private boolean ready = false;   /** Switch on debugging output */   private final boolean debug = false;   /** Hold only weak reference on callback object? */   private final boolean useWeakReference;   /** To avoid sync */   private boolean mapHasNewEntry;   /**    * Create a timer thread with a strong reference on the callback objects.    */   public Timeout() {      this("Timeout-Thread", false);   }   /**    * Create a timer thread with a strong reference on the callback objects.    *     * @param name    *           The name of the thread    */   public Timeout(String name) {      this(name, false);   }   /**    * @param name    *           The name of the thread    * @param useWeakReference    *           If true the reference on your I_Timeout implementation is only    *           weak referenced and may be garbage collected even that we hold a    *           weak reference.    */   public Timeout(String name, boolean useWeakReference) {      super(name);      this.useWeakReference = useWeakReference;      this.map = new TreeMap();      setDaemon(true);      start();      while (!ready) { // We block until our timer thread is ready         try {            Thread.sleep(1);         } catch (InterruptedException e) {         }      }   }   /**    * Get number of current used timers.    *     * @return The number of active timers    */   public int getSize() {      synchronized (map) {         return map.size();      }   }   /**    * Starts the Timeout manager thread.    */   public void run() {      Container container;      while (running) {         long delay = 100000; // sleep veeery long         container = null;         synchronized (map) {            try {               Timestamp nextWakeup = (Timestamp) map.firstKey(); // throws                                                                  // exception                                                                  // if empty               long next = nextWakeup.getMillis();               long current = System.currentTimeMillis();               delay = next - current;               if (delay <= 0) {                  container = (Container) map.remove(nextWakeup);                  if (debug) {                     long time = System.currentTimeMillis();                     long diff = time - nextWakeup.getMillis();                     System.out                           .println("Timeout occurred, calling listener with real time error of "                                 + diff + " millis");                  }               }            } catch (NoSuchElementException e) {               if (debug)                  System.out                        .println("The listener map is empty, nothing to do.");            }            this.mapHasNewEntry = false;         }         if (container != null) {            I_Timeout callback = container.getCallback();            // System.out.println("useWeakReference=" + useWeakReference + "            // callback=" + callback);            if (callback != null) {               callback.timeout(container.getUserData());            }            continue;         }         if (delay > 0) {            try {               synchronized (this) {                  ready = true; // only needed on thread creation / startup                  if (!this.mapHasNewEntry) { // If in the sync gap (~5 lines                                                // higher) a new timer was                                                // registered we need to loop                                                // again and recalculate the                                                // delay                     wait(delay);                  }               }            } catch (InterruptedException i) {               // Wakeing up, and check if there is something to do            }         }      }   }   /**    * Add a listener which gets informed after 'delay' milliseconds.    * <p />    * After the timeout happened, you are not registered any more. If you want    * to cycle timeouts, you need to register again.    * <p />    *     * @param listener    *           Your callback handle (you need to implement this interface).    * @param delay    *           The timeout in milliseconds. You can pass 0L and the Timeout    *           thread will fire immediately, this can be useful to dispatch a    *           task to the timeoutlistener    * @param userData    *           Some arbitrary data you supply, it will be routed back to you    *           when the timeout occurs through method I_Timeout.timeout().    * @return A handle which you can use to unregister with    *         removeTimeoutListener().    */   public final Timestamp addTimeoutListener(I_Timeout listener, long delay,         Object userData) {      if (listener == null) {         throw new IllegalArgumentException(ME               + ": addTimeoutListener() with listener=null");      }      Timestamp key = null;      // if (delay < 1) System.out.println(ME + ": addTimeoutListener with delay      // = " + delay);      int nanoCounter = 0;      long timeMillis = System.currentTimeMillis();      synchronized (map) {         while (true) {            long endNanos = (timeMillis + delay) * Timestamp.MILLION                  + nanoCounter;            key = new Timestamp(endNanos);            Object obj = map.get(key);            if (obj == null) {               map.put(key, new Container(this.useWeakReference, listener,                     userData));               break;            } else {               nanoCounter++; // We loop to avoid two similar keys, this should                              // happen very seldom               // System.out.println("Looping nanoCounter=" + nanoCounter);            }         }         this.mapHasNewEntry = true;      }      synchronized (this) {         notify();      }      return key;   }   /**    * Refresh a listener before the timeout happened.    * <p />

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -