View Javadoc
1 /*** 2 * Redistribution and use of this software and associated documentation 3 * ("Software"), with or without modification, are permitted provided 4 * that the following conditions are met: 5 * 6 * 1. Redistributions of source code must retain copyright 7 * statements and notices. Redistributions must also contain a 8 * copy of this document. 9 * 10 * 2. Redistributions in binary form must reproduce the 11 * above copyright notice, this list of conditions and the 12 * following disclaimer in the documentation and/or other 13 * materials provided with the distribution. 14 * 15 * 3. The name "Exolab" must not be used to endorse or promote 16 * products derived from this Software without prior written 17 * permission of Intalio. For written permission, 18 * please contact info@exolab.org. 19 * 20 * 4. Products derived from this Software may not be called "Exolab" 21 * nor may "Exolab" appear in their names without prior written 22 * permission of Intalio. Exolab is a registered 23 * trademark of Intalio. 24 * 25 * 5. Due credit should be given to the Exolab Project 26 * (http://www.exolab.org/). 27 * 28 * THIS SOFTWARE IS PROVIDED BY INTALIO AND CONTRIBUTORS 29 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT 30 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 31 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 32 * INTALIO OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 39 * OF THE POSSIBILITY OF SUCH DAMAGE. 40 * 41 * Copyright 1999-2004 (C) Intalio Inc. All Rights Reserved. 42 * 43 * $Id: Clock.java,v 1.4 2004/01/18 04:30:08 tanderson Exp $ 44 */ 45 package org.exolab.jms.util; 46 47 import org.apache.commons.logging.Log; 48 import org.apache.commons.logging.LogFactory; 49 50 51 /*** 52 * Provides an efficient mechanism for obtaining the current 53 * system time. Uses a background thread to automatically increment 54 * an internal clock and periodically synchronize with the system clock. 55 * The method {@link #clock clock} is more efficient than 56 * <code>java.lang.System.currentTimeMillis</code>, and also 57 * allows the clock to be artificially advanced for testing purposes. 58 * <p> 59 * The clock is thread-safe and consumes a single thread. 60 * <p> 61 * This class originally came from Tyrex: http://tyrex.sourceforge.net 62 * 63 * @author <a href="mailto:arkin@intalio.com">Assaf Arkin</a> 64 * @version $Revision: 1.4 $ 65 */ 66 public final class Clock extends Thread { 67 68 /*** 69 * The number of clock ticks in each unsynchronized cycle. 70 * The default is 100 milliseconds. 71 */ 72 public static final int UNSYNCH_TICKS = 100; 73 74 75 /*** 76 * The number of unsychronized cycles before the clock is 77 * synchronized with the system clock. The default is 10. 78 */ 79 public static final int SYNCH_EVERY = 10; 80 81 82 /*** 83 * The current clock. 84 */ 85 private static long _clock; 86 87 88 /*** 89 * The number of clock ticks to skip before incrementing the internal 90 * clock. 91 */ 92 private static int _unsynchTicks = UNSYNCH_TICKS; 93 94 /*** 95 * The number of cycles to skip before synchronizing with the system 96 * clock. 97 */ 98 private static int _synchEvery = SYNCH_EVERY; 99 100 101 /*** 102 * The amount of time in milliseconds by which to advance the clock 103 * compared to the system clock. 104 */ 105 private static long _advance; 106 107 108 /*** 109 * Used to adjust the clock when it gets out of synch. Based on the 110 * difference between the last clock and the system clock at the point of 111 * synchronization, divided by synchEvery. 112 */ 113 private static int _adjust; 114 115 /*** 116 * The logger 117 */ 118 private static final Log _log = LogFactory.getLog(Clock.class); 119 120 121 /*** 122 * Returns the current clock. 123 * 124 * @return The current clock 125 */ 126 public static synchronized long clock() { 127 // Synchronization is required since clock is a long. 128 return _clock; 129 } 130 131 132 /*** 133 * Sets the number of clock ticks in each unsynchronized cycle. 134 * Use zero to restore the default value. 135 * <p> 136 * The internal clock is advanced every cycle, the length of the 137 * cycle is controlled by this property. A higher value results 138 * in a lower clock resolution. 139 * 140 * @param ticks The number of clock ticks (milliseconds) for 141 * each unsynchronized cycle 142 */ 143 public static void setUnsynchTicks(int ticks) { 144 if (ticks <= 0) { 145 ticks = UNSYNCH_TICKS; 146 } else if (ticks < 100) { 147 ticks = 100; 148 } 149 _unsynchTicks = ticks; 150 } 151 152 153 /*** 154 * Returns the number of clock ticks in each unsynchronized cycle. 155 * 156 * @return The number of clock ticks (milliseconds) for 157 * each unsynchronized cycle 158 */ 159 public static int getUnsynchTicks() { 160 return _unsynchTicks; 161 } 162 163 164 /*** 165 * Sets the number of unsynchronized cycles before the clock 166 * is synchronized with the system clock. 167 * <p> 168 * Synchronization will occur every <tt>unsynchTicks * synchEvery</tt> 169 * milliseconds. The larger the value, the less accurate 170 * the clock is. 171 * 172 * @param every The number of unsynchronized cycles 173 */ 174 public static void setSynchEvery(int every) { 175 if (every <= 0) 176 every = SYNCH_EVERY; 177 _synchEvery = every; 178 } 179 180 181 /*** 182 * Artficially advances the clock. 183 * 184 * @param byMillis The number of milliseconds by which to 185 * advance the clock (must be positive) 186 */ 187 public synchronized static void advance(long byMillis) { 188 // Synchronization is required since clock is a long. 189 _advance += byMillis; 190 _clock += byMillis; 191 } 192 193 194 /*** 195 * Returns the number of milliseconds by which the clock is 196 * advanced. 197 * 198 * @return The number of milliseconds by which the clock is 199 * advanced 200 */ 201 public static long getAdvance() { 202 return _advance; 203 } 204 205 206 public void run() { 207 while (true) { 208 try { 209 for (int i = 0; i < _synchEvery; ++i) { 210 sleep(_unsynchTicks); 211 synchronized (Clock.class) { 212 _clock += _unsynchTicks + _adjust; 213 } 214 } 215 synchronize(); 216 } catch (Throwable exception) { 217 _log.error("Internal error in clock daemon", exception); 218 } 219 } 220 } 221 222 223 public static synchronized long synchronize() { 224 long current; 225 long retarded; 226 long clock; 227 int adjust; 228 229 current = System.currentTimeMillis(); 230 clock = _clock; 231 retarded = clock - _advance; 232 // Adjust clock to new difference 233 if (current != retarded) { 234 adjust = (int) (current - retarded) / _synchEvery; 235 if (adjust != 0) { 236 _adjust += adjust; 237 /* 238 if ( Configuration.verbose ) 239 Logger.tyrex.debug( "Clock late by " + ( current - retarded ) + 240 "ms -> synchronized, adjusting by " + _clock._adjust ); 241 */ 242 } 243 } 244 // Make sure clock is progressive 245 if (current > retarded) { 246 clock = current + _advance; 247 _clock = clock; 248 } 249 return clock; 250 } 251 252 253 private Clock() { 254 super("Clock Daemon"); 255 _clock = System.currentTimeMillis(); 256 setPriority(Thread.MAX_PRIORITY); 257 setDaemon(true); 258 start(); 259 } 260 261 static { 262 new Clock(); 263 } 264 265 public static void main(String[] args) { 266 long clock; 267 int count; 268 269 try { 270 count = 1000000; 271 System.out.println("Using Clock.clock()"); 272 clock = System.currentTimeMillis(); 273 for (int i = 0; i < count; ++i) { 274 if ((i % 100) == 0) 275 synchronize(); 276 else 277 clock(); 278 } 279 clock = System.currentTimeMillis() - clock; 280 System.out.println("Performed " + count + " in " + clock + "ms"); 281 System.out.println("Using System.currentTimeMillis()"); 282 clock = System.currentTimeMillis(); 283 for (int i = 0; i < count; ++i) 284 System.currentTimeMillis(); 285 clock = System.currentTimeMillis() - clock; 286 System.out.println("Performed " + count + " in " + clock + "ms"); 287 } catch (Exception except) { 288 } 289 } 290 291 292 }

This page was automatically generated by Maven