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