1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. Oracle designates this 7 * particular file as subject to the "Classpath" exception as provided 8 * by Oracle in the LICENSE file that accompanied this code. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 /* 26 * This file is available under and governed by the GNU General Public 27 * License version 2 only, as published by the Free Software Foundation. 28 * However, the following notice accompanied the original version of this 29 * file: 30 * 31 * Written by Doug Lea with assistance from members of JCP JSR-166 32 * Expert Group and released to the public domain, as explained at 33 * http://creativecommons.org/publicdomain/zero/1.0/ 34 */ 35 36 package java.util.concurrent; 37 38 import java.time.temporal.ChronoUnit; 39 import java.util.Objects; 40 41 /** 42 * A {@code TimeUnit} represents time durations at a given unit of 43 * granularity and provides utility methods to convert across units, 44 * and to perform timing and delay operations in these units. A 45 * {@code TimeUnit} does not maintain time information, but only 46 * helps organize and use time representations that may be maintained 47 * separately across various contexts. A nanosecond is defined as one 48 * thousandth of a microsecond, a microsecond as one thousandth of a 49 * millisecond, a millisecond as one thousandth of a second, a minute 50 * as sixty seconds, an hour as sixty minutes, and a day as twenty four 51 * hours. 52 * 53 * <p>A {@code TimeUnit} is mainly used to inform time-based methods 54 * how a given timing parameter should be interpreted. For example, 55 * the following code will timeout in 50 milliseconds if the {@link 56 * java.util.concurrent.locks.Lock lock} is not available: 57 * 58 * <pre> {@code 59 * Lock lock = ...; 60 * if (lock.tryLock(50L, TimeUnit.MILLISECONDS)) ...}</pre> 61 * 62 * while this code will timeout in 50 seconds: 63 * <pre> {@code 64 * Lock lock = ...; 65 * if (lock.tryLock(50L, TimeUnit.SECONDS)) ...}</pre> 66 * 67 * Note however, that there is no guarantee that a particular timeout 68 * implementation will be able to notice the passage of time at the 69 * same granularity as the given {@code TimeUnit}. 70 * 71 * @since 1.5 72 * @author Doug Lea 73 */ 74 public enum TimeUnit { 75 /** 76 * Time unit representing one thousandth of a microsecond. 77 */ 78 NANOSECONDS { 79 public long toNanos(long d) { return d; } 80 public long toMicros(long d) { return d/(C1/C0); } 81 public long toMillis(long d) { return d/(C2/C0); } 82 public long toSeconds(long d) { return d/(C3/C0); } 83 public long toMinutes(long d) { return d/(C4/C0); } 84 public long toHours(long d) { return d/(C5/C0); } 85 public long toDays(long d) { return d/(C6/C0); } 86 public long convert(long d, TimeUnit u) { return u.toNanos(d); } 87 int excessNanos(long d, long m) { return (int)(d - (m*C2)); } 88 }, 89 90 /** 91 * Time unit representing one thousandth of a millisecond. 92 */ 93 MICROSECONDS { 94 public long toNanos(long d) { return x(d, C1/C0, MAX/(C1/C0)); } 95 public long toMicros(long d) { return d; } 96 public long toMillis(long d) { return d/(C2/C1); } 97 public long toSeconds(long d) { return d/(C3/C1); } 98 public long toMinutes(long d) { return d/(C4/C1); } 99 public long toHours(long d) { return d/(C5/C1); } 100 public long toDays(long d) { return d/(C6/C1); } 101 public long convert(long d, TimeUnit u) { return u.toMicros(d); } 102 int excessNanos(long d, long m) { return (int)((d*C1) - (m*C2)); } 103 }, 104 105 /** 106 * Time unit representing one thousandth of a second. 107 */ 108 MILLISECONDS { 109 public long toNanos(long d) { return x(d, C2/C0, MAX/(C2/C0)); } 110 public long toMicros(long d) { return x(d, C2/C1, MAX/(C2/C1)); } 111 public long toMillis(long d) { return d; } 112 public long toSeconds(long d) { return d/(C3/C2); } 113 public long toMinutes(long d) { return d/(C4/C2); } 114 public long toHours(long d) { return d/(C5/C2); } 115 public long toDays(long d) { return d/(C6/C2); } 116 public long convert(long d, TimeUnit u) { return u.toMillis(d); } 117 int excessNanos(long d, long m) { return 0; } 118 }, 119 120 /** 121 * Time unit representing one second. 122 */ 123 SECONDS { 124 public long toNanos(long d) { return x(d, C3/C0, MAX/(C3/C0)); } 125 public long toMicros(long d) { return x(d, C3/C1, MAX/(C3/C1)); } 126 public long toMillis(long d) { return x(d, C3/C2, MAX/(C3/C2)); } 127 public long toSeconds(long d) { return d; } 128 public long toMinutes(long d) { return d/(C4/C3); } 129 public long toHours(long d) { return d/(C5/C3); } 130 public long toDays(long d) { return d/(C6/C3); } 131 public long convert(long d, TimeUnit u) { return u.toSeconds(d); } 132 int excessNanos(long d, long m) { return 0; } 133 }, 134 135 /** 136 * Time unit representing sixty seconds. 137 * @since 1.6 138 */ 139 MINUTES { 140 public long toNanos(long d) { return x(d, C4/C0, MAX/(C4/C0)); } 141 public long toMicros(long d) { return x(d, C4/C1, MAX/(C4/C1)); } 142 public long toMillis(long d) { return x(d, C4/C2, MAX/(C4/C2)); } 143 public long toSeconds(long d) { return x(d, C4/C3, MAX/(C4/C3)); } 144 public long toMinutes(long d) { return d; } 145 public long toHours(long d) { return d/(C5/C4); } 146 public long toDays(long d) { return d/(C6/C4); } 147 public long convert(long d, TimeUnit u) { return u.toMinutes(d); } 148 int excessNanos(long d, long m) { return 0; } 149 }, 150 151 /** 152 * Time unit representing sixty minutes. 153 * @since 1.6 154 */ 155 HOURS { 156 public long toNanos(long d) { return x(d, C5/C0, MAX/(C5/C0)); } 157 public long toMicros(long d) { return x(d, C5/C1, MAX/(C5/C1)); } 158 public long toMillis(long d) { return x(d, C5/C2, MAX/(C5/C2)); } 159 public long toSeconds(long d) { return x(d, C5/C3, MAX/(C5/C3)); } 160 public long toMinutes(long d) { return x(d, C5/C4, MAX/(C5/C4)); } 161 public long toHours(long d) { return d; } 162 public long toDays(long d) { return d/(C6/C5); } 163 public long convert(long d, TimeUnit u) { return u.toHours(d); } 164 int excessNanos(long d, long m) { return 0; } 165 }, 166 167 /** 168 * Time unit representing twenty four hours. 169 * @since 1.6 170 */ 171 DAYS { 172 public long toNanos(long d) { return x(d, C6/C0, MAX/(C6/C0)); } 173 public long toMicros(long d) { return x(d, C6/C1, MAX/(C6/C1)); } 174 public long toMillis(long d) { return x(d, C6/C2, MAX/(C6/C2)); } 175 public long toSeconds(long d) { return x(d, C6/C3, MAX/(C6/C3)); } 176 public long toMinutes(long d) { return x(d, C6/C4, MAX/(C6/C4)); } 177 public long toHours(long d) { return x(d, C6/C5, MAX/(C6/C5)); } 178 public long toDays(long d) { return d; } 179 public long convert(long d, TimeUnit u) { return u.toDays(d); } 180 int excessNanos(long d, long m) { return 0; } 181 }; 182 183 // Handy constants for conversion methods 184 static final long C0 = 1L; 185 static final long C1 = C0 * 1000L; 186 static final long C2 = C1 * 1000L; 187 static final long C3 = C2 * 1000L; 188 static final long C4 = C3 * 60L; 189 static final long C5 = C4 * 60L; 190 static final long C6 = C5 * 24L; 191 192 static final long MAX = Long.MAX_VALUE; 193 194 /** 195 * Scale d by m, checking for overflow. 196 * This has a short name to make above code more readable. 197 */ 198 static long x(long d, long m, long over) { 199 if (d > +over) return Long.MAX_VALUE; 200 if (d < -over) return Long.MIN_VALUE; 201 return d * m; 202 } 203 204 // To maintain full signature compatibility with 1.5, and to improve the 205 // clarity of the generated javadoc (see 6287639: Abstract methods in 206 // enum classes should not be listed as abstract), method convert 207 // etc. are not declared abstract but otherwise act as abstract methods. 208 209 /** 210 * Converts the given time duration in the given unit to this unit. 211 * Conversions from finer to coarser granularities truncate, so 212 * lose precision. For example, converting {@code 999} milliseconds 213 * to seconds results in {@code 0}. Conversions from coarser to 214 * finer granularities with arguments that would numerically 215 * overflow saturate to {@code Long.MIN_VALUE} if negative or 216 * {@code Long.MAX_VALUE} if positive. 217 * 218 * <p>For example, to convert 10 minutes to milliseconds, use: 219 * {@code TimeUnit.MILLISECONDS.convert(10L, TimeUnit.MINUTES)} 220 * 221 * @param sourceDuration the time duration in the given {@code sourceUnit} 222 * @param sourceUnit the unit of the {@code sourceDuration} argument 223 * @return the converted duration in this unit, 224 * or {@code Long.MIN_VALUE} if conversion would negatively 225 * overflow, or {@code Long.MAX_VALUE} if it would positively overflow. 226 */ 227 public long convert(long sourceDuration, TimeUnit sourceUnit) { 228 throw new AbstractMethodError(); 229 } 230 231 /** 232 * Equivalent to 233 * {@link #convert(long, TimeUnit) NANOSECONDS.convert(duration, this)}. 234 * @param duration the duration 235 * @return the converted duration, 236 * or {@code Long.MIN_VALUE} if conversion would negatively 237 * overflow, or {@code Long.MAX_VALUE} if it would positively overflow. 238 */ 239 public long toNanos(long duration) { 240 throw new AbstractMethodError(); 241 } 242 243 /** 244 * Equivalent to 245 * {@link #convert(long, TimeUnit) MICROSECONDS.convert(duration, this)}. 246 * @param duration the duration 247 * @return the converted duration, 248 * or {@code Long.MIN_VALUE} if conversion would negatively 249 * overflow, or {@code Long.MAX_VALUE} if it would positively overflow. 250 */ 251 public long toMicros(long duration) { 252 throw new AbstractMethodError(); 253 } 254 255 /** 256 * Equivalent to 257 * {@link #convert(long, TimeUnit) MILLISECONDS.convert(duration, this)}. 258 * @param duration the duration 259 * @return the converted duration, 260 * or {@code Long.MIN_VALUE} if conversion would negatively 261 * overflow, or {@code Long.MAX_VALUE} if it would positively overflow. 262 */ 263 public long toMillis(long duration) { 264 throw new AbstractMethodError(); 265 } 266 267 /** 268 * Equivalent to 269 * {@link #convert(long, TimeUnit) SECONDS.convert(duration, this)}. 270 * @param duration the duration 271 * @return the converted duration, 272 * or {@code Long.MIN_VALUE} if conversion would negatively 273 * overflow, or {@code Long.MAX_VALUE} if it would positively overflow. 274 */ 275 public long toSeconds(long duration) { 276 throw new AbstractMethodError(); 277 } 278 279 /** 280 * Equivalent to 281 * {@link #convert(long, TimeUnit) MINUTES.convert(duration, this)}. 282 * @param duration the duration 283 * @return the converted duration, 284 * or {@code Long.MIN_VALUE} if conversion would negatively 285 * overflow, or {@code Long.MAX_VALUE} if it would positively overflow. 286 * @since 1.6 287 */ 288 public long toMinutes(long duration) { 289 throw new AbstractMethodError(); 290 } 291 292 /** 293 * Equivalent to 294 * {@link #convert(long, TimeUnit) HOURS.convert(duration, this)}. 295 * @param duration the duration 296 * @return the converted duration, 297 * or {@code Long.MIN_VALUE} if conversion would negatively 298 * overflow, or {@code Long.MAX_VALUE} if it would positively overflow. 299 * @since 1.6 300 */ 301 public long toHours(long duration) { 302 throw new AbstractMethodError(); 303 } 304 305 /** 306 * Equivalent to 307 * {@link #convert(long, TimeUnit) DAYS.convert(duration, this)}. 308 * @param duration the duration 309 * @return the converted duration 310 * @since 1.6 311 */ 312 public long toDays(long duration) { 313 throw new AbstractMethodError(); 314 } 315 316 /** 317 * Utility to compute the excess-nanosecond argument to wait, 318 * sleep, join. 319 * @param d the duration 320 * @param m the number of milliseconds 321 * @return the number of nanoseconds 322 */ 323 abstract int excessNanos(long d, long m); 324 325 /** 326 * Performs a timed {@link Object#wait(long, int) Object.wait} 327 * using this time unit. 328 * This is a convenience method that converts timeout arguments 329 * into the form required by the {@code Object.wait} method. 330 * 331 * <p>For example, you could implement a blocking {@code poll} 332 * method (see {@link BlockingQueue#poll BlockingQueue.poll}) 333 * using: 334 * 335 * <pre> {@code 336 * public synchronized Object poll(long timeout, TimeUnit unit) 337 * throws InterruptedException { 338 * while (empty) { 339 * unit.timedWait(this, timeout); 340 * ... 341 * } 342 * }}</pre> 343 * 344 * @param obj the object to wait on 345 * @param timeout the maximum time to wait. If less than 346 * or equal to zero, do not wait at all. 347 * @throws InterruptedException if interrupted while waiting 348 */ 349 public void timedWait(Object obj, long timeout) 350 throws InterruptedException { 351 if (timeout > 0) { 352 long ms = toMillis(timeout); 353 int ns = excessNanos(timeout, ms); 354 obj.wait(ms, ns); 355 } 356 } 357 358 /** 359 * Performs a timed {@link Thread#join(long, int) Thread.join} 360 * using this time unit. 361 * This is a convenience method that converts time arguments into the 362 * form required by the {@code Thread.join} method. 363 * 364 * @param thread the thread to wait for 365 * @param timeout the maximum time to wait. If less than 366 * or equal to zero, do not wait at all. 367 * @throws InterruptedException if interrupted while waiting 368 */ 369 public void timedJoin(Thread thread, long timeout) 370 throws InterruptedException { 371 if (timeout > 0) { 372 long ms = toMillis(timeout); 373 int ns = excessNanos(timeout, ms); 374 thread.join(ms, ns); 375 } 376 } 377 378 /** 379 * Performs a {@link Thread#sleep(long, int) Thread.sleep} using 380 * this time unit. 381 * This is a convenience method that converts time arguments into the 382 * form required by the {@code Thread.sleep} method. 383 * 384 * @param timeout the minimum time to sleep. If less than 385 * or equal to zero, do not sleep at all. 386 * @throws InterruptedException if interrupted while sleeping 387 */ 388 public void sleep(long timeout) throws InterruptedException { 389 if (timeout > 0) { 390 long ms = toMillis(timeout); 391 int ns = excessNanos(timeout, ms); 392 Thread.sleep(ms, ns); 393 } 394 } 395 396 /** 397 * Converts a {@code TimeUnit} to an equivalent {@code ChronoUnit}. 398 * 399 * @param timeUnit the timeUnit to convert, not null 400 * @return the converted equivalent chronoUnit 401 * @throws IllegalArgumentException if the unit cannot be converted 402 * @since 9 403 */ 404 public static ChronoUnit toChronoUnit(TimeUnit timeUnit) { 405 Objects.requireNonNull(timeUnit, "timeUnit"); 406 switch (timeUnit) { 407 case NANOSECONDS: 408 return ChronoUnit.NANOS; 409 case MICROSECONDS: 410 return ChronoUnit.MICROS; 411 case MILLISECONDS: 412 return ChronoUnit.MILLIS; 413 case SECONDS: 414 return ChronoUnit.SECONDS; 415 case MINUTES: 416 return ChronoUnit.MINUTES; 417 case HOURS: 418 return ChronoUnit.HOURS; 419 case DAYS: 420 return ChronoUnit.DAYS; 421 default: 422 throw new IllegalArgumentException("Unknown TimeUnit"); 423 } 424 } 425 426 /** 427 * Converts a {@code ChronoUnit} to an equivalent {@code TimeUnit}. 428 * 429 * @param chronoUnit the unit to convert, not null 430 * @return the converted equivalent timeUnit 431 * @throws IllegalArgumentException if the unit cannot be converted 432 * @since 9 433 */ 434 public static TimeUnit of(ChronoUnit chronoUnit) { 435 Objects.requireNonNull(chronoUnit, "chronoUnit"); 436 switch (chronoUnit) { 437 case NANOS: 438 return TimeUnit.NANOSECONDS; 439 case MICROS: 440 return TimeUnit.MICROSECONDS; 441 case MILLIS: 442 return TimeUnit.MILLISECONDS; 443 case SECONDS: 444 return TimeUnit.SECONDS; 445 case MINUTES: 446 return TimeUnit.MINUTES; 447 case HOURS: 448 return TimeUnit.HOURS; 449 case DAYS: 450 return TimeUnit.DAYS; 451 default: 452 throw new IllegalArgumentException("No TimeUnit equivalent for " + chronoUnit); 453 } 454 } 455 456 }