} /* * Inserts the timer back into the queue. This method * is used by a callback thread after it has called the * timer owner's tick() method. This method recomputes * the sleepUntil field. * Assumes the caller has the TimerThread and Timer monitor. */ protected static void requeue(Timer timer) { if (!timer.stopped) { long now = System.currentTimeMillis(); if (timer.regular) { timer.sleepUntil += timer.interval; } else { timer.sleepUntil = now + timer.interval; } enqueue(timer); } else if (debug) { System.out.println(Thread.currentThread().getName() + ": requeue " + timer.interval + ": no-op"); } }} /* This class implements a simple thread whose only purpose is to call atimer owner's tick() method. A small fixed-sized pool of threads ismaintained and is protected by the class monitor. If the pool isexhausted, a new thread is temporarily created and destroyed whendone. A thread that's in the pool waits on it's own monitor. When thethread is retrieved from the pool, the retriever notifies the thread'smonitor. */ class TimerTickThread extends Thread { /* * Maximum size of the thread pool. */ static final int MAX_POOL_SIZE = 3; /* * Number of threads in the pool. */ static int curPoolSize = 0; /* * The pool of timer threads. */ static TimerTickThread pool = null; /* * Is used when linked into the thread pool. */ TimerTickThread next = null; /* * This is the handle to the timer whose owner's * tick() method will be called. */ Timer timer; /* * The value of a timer's sleepUntil value is captured here. * This is used to determine whether or not the timer should * be reinserted into the queue. If the timer's sleepUntil * value has changed, the timer is not reinserted. */ long lastSleepUntil; /* * Creates a new callback thread to call the timer owner's * tick() method. A thread is taken from the pool if one * is available, otherwise, a new thread is created. * The thread handle is returned. */ protected static synchronized TimerTickThread call( Timer timer, long sleepUntil) { TimerTickThread thread = pool; if (thread == null) { // create one. thread = new TimerTickThread(); thread.timer = timer; thread.lastSleepUntil = sleepUntil; thread.start(); } else { pool = pool.next; thread.timer = timer; thread.lastSleepUntil = sleepUntil; synchronized (thread) { thread.notify(); } } return thread; } /* * Returns false if the thread should simply exit; * otherwise the thread is returned the pool, where * it waits to be notified. (I did try to use the * class monitor but the time between the notify * and breaking out of the wait seemed to take * significantly longer; need to look into this later.) */ private boolean returnToPool() { synchronized (getClass()) { if (curPoolSize >= MAX_POOL_SIZE) { return false; } next = pool; pool = this; curPoolSize++; timer = null; } while (timer == null) { synchronized (this) { try { wait(); } catch (InterruptedException ex) { // Just drop through and retest timer. } } } synchronized (getClass()) { curPoolSize--; } return true; } public void run() { do { timer.owner.tick(timer); synchronized (TimerThread.timerThread) { synchronized (timer) { if (lastSleepUntil == timer.sleepUntil) { TimerThread.requeue(timer); } } } } while (returnToPool()); }}Lines 501–647 of 647. Previous lines
} /* * Inserts the timer back into the queue. This method * is used by a callback thread after it has called the * timer owner's tick() method. This method recomputes * the sleepUntil field. * Assumes the caller has the TimerThread and Timer monitor. */ protected static void requeue(Timer timer) { if (!timer.stopped) { long now = System.currentTimeMillis(); if (timer.regular) { timer.sleepUntil += timer.interval; } else { timer.sleepUntil = now + timer.interval; } enqueue(timer); } else if (debug) { System.out.println(Thread.currentThread().getName() + ": requeue " + timer.interval + ": no-op"); } } } /* This class implements a simple thread whose only purpose is to call a timer owner's tick() method. A small fixed-sized pool of threads is maintained and is protected by the class monitor. If the pool is exhausted, a new thread is temporarily created and destroyed when done. A thread that's in the pool waits on it's own monitor. When the thread is retrieved from the pool, the retriever notifies the thread's monitor. */ class TimerTickThread extends Thread { /* * Maximum size of the thread pool. */ static final int MAX_POOL_SIZE = 3; /* * Number of threads in the pool. */ static int curPoolSize = 0; /* * The pool of timer threads. */ static TimerTickThread pool = null; /* * Is used when linked into the thread pool. */ TimerTickThread next = null; /* * This is the handle to the timer whose owner's * tick() method will be called. */ Timer timer; /* * The value of a timer's sleepUntil value is captured here. * This is used to determine whether or not the timer should * be reinserted into the queue. If the timer's sleepUntil * value has changed, the timer is not reinserted. */ long lastSleepUntil; /* * Creates a new callback thread to call the timer owner's * tick() method. A thread is taken from the pool if one * is available, otherwise, a new thread is created. * The thread handle is returned. */ protected static synchronized TimerTickThread call( Timer timer, long sleepUntil) { TimerTickThread thread = pool; if (thread == null) { // create one. thread = new TimerTickThread(); thread.timer = timer; thread.lastSleepUntil = sleepUntil; thread.start(); } else { pool = pool.next; thread.timer = timer; thread.lastSleepUntil = sleepUntil; synchronized (thread) { thread.notify(); } } return thread; } /* * Returns false if the thread should simply exit; * otherwise the thread is returned the pool, where * it waits to be notified. (I did try to use the * class monitor but the time between the notify * and breaking out of the wait seemed to take * significantly longer; need to look into this later.) */ private boolean returnToPool() { synchronized (getClass()) { if (curPoolSize >= MAX_POOL_SIZE) { return false; } next = pool; pool = this; curPoolSize++; timer = null; } while (timer == null) { synchronized (this) { try { wait(); } catch (InterruptedException ex) { // Just drop through and retest timer. } } } synchronized (getClass()) { curPoolSize--; } return true; } public void run() { do { timer.owner.tick(timer); synchronized (TimerThread.timerThread) { synchronized (timer) { if (lastSleepUntil == timer.sleepUntil) { TimerThread.requeue(timer); } } } } while (returnToPool()); } }