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