1 /* 2 * Written by Doug Lea with assistance from members of JCP JSR-166 3 * Expert Group and released to the public domain, as explained at 4 * http://creativecommons.org/licenses/publicdomain 5 */ 6 7 package java.util.concurrent; 8 9 /** 10 * A <tt>TimeUnit</tt> represents time durations at a given unit of 11 * granularity and provides utility methods to convert across units, 12 * and to perform timing and delay operations in these units. A 13 * <tt>TimeUnit</tt> does not maintain time information, but only 14 * helps organize and use time representations that may be maintained 15 * separately across various contexts. A nanosecond is defined as one 16 * thousandth of a microsecond, a microsecond as one thousandth of a 17 * millisecond, a millisecond as one thousandth of a second, a minute 18 * as sixty seconds, an hour as sixty minutes, and a day as twenty four 19 * hours. 20 * 21 * <p>A <tt>TimeUnit</tt> is mainly used to inform time-based methods 22 * how a given timing parameter should be interpreted. For example, 23 * the following code will timeout in 50 milliseconds if the {@link 24 * java.util.concurrent.locks.Lock lock} is not available: 25 * 26 * <pre> Lock lock = ...; 27 * if (lock.tryLock(50L, TimeUnit.MILLISECONDS)) ... 28 * </pre> 29 * while this code will timeout in 50 seconds: 30 * <pre> 31 * Lock lock = ...; 32 * if (lock.tryLock(50L, TimeUnit.SECONDS)) ... 33 * </pre> 34 * 35 * Note however, that there is no guarantee that a particular timeout 36 * implementation will be able to notice the passage of time at the 37 * same granularity as the given <tt>TimeUnit</tt>. 38 * 39 * @since 1.5 40 * @author Doug Lea 41 */ 42 public enum TimeUnit { 43 NANOSECONDS { toNanos(long d)44 public long toNanos(long d) { return d; } toMicros(long d)45 public long toMicros(long d) { return d/(C1/C0); } toMillis(long d)46 public long toMillis(long d) { return d/(C2/C0); } toSeconds(long d)47 public long toSeconds(long d) { return d/(C3/C0); } toMinutes(long d)48 public long toMinutes(long d) { return d/(C4/C0); } toHours(long d)49 public long toHours(long d) { return d/(C5/C0); } toDays(long d)50 public long toDays(long d) { return d/(C6/C0); } convert(long d, TimeUnit u)51 public long convert(long d, TimeUnit u) { return u.toNanos(d); } excessNanos(long d, long m)52 int excessNanos(long d, long m) { return (int)(d - (m*C2)); } 53 }, 54 MICROSECONDS { toNanos(long d)55 public long toNanos(long d) { return x(d, C1/C0, MAX/(C1/C0)); } toMicros(long d)56 public long toMicros(long d) { return d; } toMillis(long d)57 public long toMillis(long d) { return d/(C2/C1); } toSeconds(long d)58 public long toSeconds(long d) { return d/(C3/C1); } toMinutes(long d)59 public long toMinutes(long d) { return d/(C4/C1); } toHours(long d)60 public long toHours(long d) { return d/(C5/C1); } toDays(long d)61 public long toDays(long d) { return d/(C6/C1); } convert(long d, TimeUnit u)62 public long convert(long d, TimeUnit u) { return u.toMicros(d); } excessNanos(long d, long m)63 int excessNanos(long d, long m) { return (int)((d*C1) - (m*C2)); } 64 }, 65 MILLISECONDS { toNanos(long d)66 public long toNanos(long d) { return x(d, C2/C0, MAX/(C2/C0)); } toMicros(long d)67 public long toMicros(long d) { return x(d, C2/C1, MAX/(C2/C1)); } toMillis(long d)68 public long toMillis(long d) { return d; } toSeconds(long d)69 public long toSeconds(long d) { return d/(C3/C2); } toMinutes(long d)70 public long toMinutes(long d) { return d/(C4/C2); } toHours(long d)71 public long toHours(long d) { return d/(C5/C2); } toDays(long d)72 public long toDays(long d) { return d/(C6/C2); } convert(long d, TimeUnit u)73 public long convert(long d, TimeUnit u) { return u.toMillis(d); } excessNanos(long d, long m)74 int excessNanos(long d, long m) { return 0; } 75 }, 76 SECONDS { toNanos(long d)77 public long toNanos(long d) { return x(d, C3/C0, MAX/(C3/C0)); } toMicros(long d)78 public long toMicros(long d) { return x(d, C3/C1, MAX/(C3/C1)); } toMillis(long d)79 public long toMillis(long d) { return x(d, C3/C2, MAX/(C3/C2)); } toSeconds(long d)80 public long toSeconds(long d) { return d; } toMinutes(long d)81 public long toMinutes(long d) { return d/(C4/C3); } toHours(long d)82 public long toHours(long d) { return d/(C5/C3); } toDays(long d)83 public long toDays(long d) { return d/(C6/C3); } convert(long d, TimeUnit u)84 public long convert(long d, TimeUnit u) { return u.toSeconds(d); } excessNanos(long d, long m)85 int excessNanos(long d, long m) { return 0; } 86 }, 87 MINUTES { toNanos(long d)88 public long toNanos(long d) { return x(d, C4/C0, MAX/(C4/C0)); } toMicros(long d)89 public long toMicros(long d) { return x(d, C4/C1, MAX/(C4/C1)); } toMillis(long d)90 public long toMillis(long d) { return x(d, C4/C2, MAX/(C4/C2)); } toSeconds(long d)91 public long toSeconds(long d) { return x(d, C4/C3, MAX/(C4/C3)); } toMinutes(long d)92 public long toMinutes(long d) { return d; } toHours(long d)93 public long toHours(long d) { return d/(C5/C4); } toDays(long d)94 public long toDays(long d) { return d/(C6/C4); } convert(long d, TimeUnit u)95 public long convert(long d, TimeUnit u) { return u.toMinutes(d); } excessNanos(long d, long m)96 int excessNanos(long d, long m) { return 0; } 97 }, 98 HOURS { toNanos(long d)99 public long toNanos(long d) { return x(d, C5/C0, MAX/(C5/C0)); } toMicros(long d)100 public long toMicros(long d) { return x(d, C5/C1, MAX/(C5/C1)); } toMillis(long d)101 public long toMillis(long d) { return x(d, C5/C2, MAX/(C5/C2)); } toSeconds(long d)102 public long toSeconds(long d) { return x(d, C5/C3, MAX/(C5/C3)); } toMinutes(long d)103 public long toMinutes(long d) { return x(d, C5/C4, MAX/(C5/C4)); } toHours(long d)104 public long toHours(long d) { return d; } toDays(long d)105 public long toDays(long d) { return d/(C6/C5); } convert(long d, TimeUnit u)106 public long convert(long d, TimeUnit u) { return u.toHours(d); } excessNanos(long d, long m)107 int excessNanos(long d, long m) { return 0; } 108 }, 109 DAYS { toNanos(long d)110 public long toNanos(long d) { return x(d, C6/C0, MAX/(C6/C0)); } toMicros(long d)111 public long toMicros(long d) { return x(d, C6/C1, MAX/(C6/C1)); } toMillis(long d)112 public long toMillis(long d) { return x(d, C6/C2, MAX/(C6/C2)); } toSeconds(long d)113 public long toSeconds(long d) { return x(d, C6/C3, MAX/(C6/C3)); } toMinutes(long d)114 public long toMinutes(long d) { return x(d, C6/C4, MAX/(C6/C4)); } toHours(long d)115 public long toHours(long d) { return x(d, C6/C5, MAX/(C6/C5)); } toDays(long d)116 public long toDays(long d) { return d; } convert(long d, TimeUnit u)117 public long convert(long d, TimeUnit u) { return u.toDays(d); } excessNanos(long d, long m)118 int excessNanos(long d, long m) { return 0; } 119 }; 120 121 // Handy constants for conversion methods 122 static final long C0 = 1L; 123 static final long C1 = C0 * 1000L; 124 static final long C2 = C1 * 1000L; 125 static final long C3 = C2 * 1000L; 126 static final long C4 = C3 * 60L; 127 static final long C5 = C4 * 60L; 128 static final long C6 = C5 * 24L; 129 130 static final long MAX = Long.MAX_VALUE; 131 132 /** 133 * Scale d by m, checking for overflow. 134 * This has a short name to make above code more readable. 135 */ x(long d, long m, long over)136 static long x(long d, long m, long over) { 137 if (d > over) return Long.MAX_VALUE; 138 if (d < -over) return Long.MIN_VALUE; 139 return d * m; 140 } 141 142 // To maintain full signature compatibility with 1.5, and to improve the 143 // clarity of the generated javadoc (see 6287639: Abstract methods in 144 // enum classes should not be listed as abstract), method convert 145 // etc. are not declared abstract but otherwise act as abstract methods. 146 147 /** 148 * Convert the given time duration in the given unit to this 149 * unit. Conversions from finer to coarser granularities 150 * truncate, so lose precision. For example converting 151 * <tt>999</tt> milliseconds to seconds results in 152 * <tt>0</tt>. Conversions from coarser to finer granularities 153 * with arguments that would numerically overflow saturate to 154 * <tt>Long.MIN_VALUE</tt> if negative or <tt>Long.MAX_VALUE</tt> 155 * if positive. 156 * 157 * <p>For example, to convert 10 minutes to milliseconds, use: 158 * <tt>TimeUnit.MILLISECONDS.convert(10L, TimeUnit.MINUTES)</tt> 159 * 160 * @param sourceDuration the time duration in the given <tt>sourceUnit</tt> 161 * @param sourceUnit the unit of the <tt>sourceDuration</tt> argument 162 * @return the converted duration in this unit, 163 * or <tt>Long.MIN_VALUE</tt> if conversion would negatively 164 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow. 165 */ convert(long sourceDuration, TimeUnit sourceUnit)166 public long convert(long sourceDuration, TimeUnit sourceUnit) { 167 throw new AbstractMethodError(); 168 } 169 170 /** 171 * Equivalent to <tt>NANOSECONDS.convert(duration, this)</tt>. 172 * @param duration the duration 173 * @return the converted duration, 174 * or <tt>Long.MIN_VALUE</tt> if conversion would negatively 175 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow. 176 * @see #convert 177 */ toNanos(long duration)178 public long toNanos(long duration) { 179 throw new AbstractMethodError(); 180 } 181 182 /** 183 * Equivalent to <tt>MICROSECONDS.convert(duration, this)</tt>. 184 * @param duration the duration 185 * @return the converted duration, 186 * or <tt>Long.MIN_VALUE</tt> if conversion would negatively 187 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow. 188 * @see #convert 189 */ toMicros(long duration)190 public long toMicros(long duration) { 191 throw new AbstractMethodError(); 192 } 193 194 /** 195 * Equivalent to <tt>MILLISECONDS.convert(duration, this)</tt>. 196 * @param duration the duration 197 * @return the converted duration, 198 * or <tt>Long.MIN_VALUE</tt> if conversion would negatively 199 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow. 200 * @see #convert 201 */ toMillis(long duration)202 public long toMillis(long duration) { 203 throw new AbstractMethodError(); 204 } 205 206 /** 207 * Equivalent to <tt>SECONDS.convert(duration, this)</tt>. 208 * @param duration the duration 209 * @return the converted duration, 210 * or <tt>Long.MIN_VALUE</tt> if conversion would negatively 211 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow. 212 * @see #convert 213 */ toSeconds(long duration)214 public long toSeconds(long duration) { 215 throw new AbstractMethodError(); 216 } 217 218 /** 219 * Equivalent to <tt>MINUTES.convert(duration, this)</tt>. 220 * @param duration the duration 221 * @return the converted duration, 222 * or <tt>Long.MIN_VALUE</tt> if conversion would negatively 223 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow. 224 * @see #convert 225 * @since 1.6 226 */ toMinutes(long duration)227 public long toMinutes(long duration) { 228 throw new AbstractMethodError(); 229 } 230 231 /** 232 * Equivalent to <tt>HOURS.convert(duration, this)</tt>. 233 * @param duration the duration 234 * @return the converted duration, 235 * or <tt>Long.MIN_VALUE</tt> if conversion would negatively 236 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow. 237 * @see #convert 238 * @since 1.6 239 */ toHours(long duration)240 public long toHours(long duration) { 241 throw new AbstractMethodError(); 242 } 243 244 /** 245 * Equivalent to <tt>DAYS.convert(duration, this)</tt>. 246 * @param duration the duration 247 * @return the converted duration 248 * @see #convert 249 * @since 1.6 250 */ toDays(long duration)251 public long toDays(long duration) { 252 throw new AbstractMethodError(); 253 } 254 255 /** 256 * Utility to compute the excess-nanosecond argument to wait, 257 * sleep, join. 258 * @param d the duration 259 * @param m the number of milliseconds 260 * @return the number of nanoseconds 261 */ excessNanos(long d, long m)262 abstract int excessNanos(long d, long m); 263 264 /** 265 * Performs a timed {@link Object#wait(long, int) Object.wait} 266 * using this time unit. 267 * This is a convenience method that converts timeout arguments 268 * into the form required by the <tt>Object.wait</tt> method. 269 * 270 * <p>For example, you could implement a blocking <tt>poll</tt> 271 * method (see {@link BlockingQueue#poll BlockingQueue.poll}) 272 * using: 273 * 274 * <pre> {@code 275 * public synchronized Object poll(long timeout, TimeUnit unit) 276 * throws InterruptedException { 277 * while (empty) { 278 * unit.timedWait(this, timeout); 279 * ... 280 * } 281 * }}</pre> 282 * 283 * @param obj the object to wait on 284 * @param timeout the maximum time to wait. If less than 285 * or equal to zero, do not wait at all. 286 * @throws InterruptedException if interrupted while waiting 287 */ timedWait(Object obj, long timeout)288 public void timedWait(Object obj, long timeout) 289 throws InterruptedException { 290 if (timeout > 0) { 291 long ms = toMillis(timeout); 292 int ns = excessNanos(timeout, ms); 293 obj.wait(ms, ns); 294 } 295 } 296 297 /** 298 * Performs a timed {@link Thread#join(long, int) Thread.join} 299 * using this time unit. 300 * This is a convenience method that converts time arguments into the 301 * form required by the <tt>Thread.join</tt> method. 302 * 303 * @param thread the thread to wait for 304 * @param timeout the maximum time to wait. If less than 305 * or equal to zero, do not wait at all. 306 * @throws InterruptedException if interrupted while waiting 307 */ timedJoin(Thread thread, long timeout)308 public void timedJoin(Thread thread, long timeout) 309 throws InterruptedException { 310 if (timeout > 0) { 311 long ms = toMillis(timeout); 312 int ns = excessNanos(timeout, ms); 313 thread.join(ms, ns); 314 } 315 } 316 317 /** 318 * Performs a {@link Thread#sleep(long, int) Thread.sleep} using 319 * this time unit. 320 * This is a convenience method that converts time arguments into the 321 * form required by the <tt>Thread.sleep</tt> method. 322 * 323 * @param timeout the minimum time to sleep. If less than 324 * or equal to zero, do not sleep at all. 325 * @throws InterruptedException if interrupted while sleeping 326 */ sleep(long timeout)327 public void sleep(long timeout) throws InterruptedException { 328 if (timeout > 0) { 329 long ms = toMillis(timeout); 330 int ns = excessNanos(timeout, ms); 331 Thread.sleep(ms, ns); 332 } 333 } 334 335 } 336