TimeUnit.java revision 51b1b6997fd3f980076b8081f7f1165ccc2a4008
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 36package java.util.concurrent; 37 38/** 39 * A <tt>TimeUnit</tt> represents time durations at a given unit of 40 * granularity and provides utility methods to convert across units, 41 * and to perform timing and delay operations in these units. A 42 * <tt>TimeUnit</tt> does not maintain time information, but only 43 * helps organize and use time representations that may be maintained 44 * separately across various contexts. A nanosecond is defined as one 45 * thousandth of a microsecond, a microsecond as one thousandth of a 46 * millisecond, a millisecond as one thousandth of a second, a minute 47 * as sixty seconds, an hour as sixty minutes, and a day as twenty four 48 * hours. 49 * 50 * <p>A <tt>TimeUnit</tt> is mainly used to inform time-based methods 51 * how a given timing parameter should be interpreted. For example, 52 * the following code will timeout in 50 milliseconds if the {@link 53 * java.util.concurrent.locks.Lock lock} is not available: 54 * 55 * <pre> Lock lock = ...; 56 * if (lock.tryLock(50L, TimeUnit.MILLISECONDS)) ... 57 * </pre> 58 * while this code will timeout in 50 seconds: 59 * <pre> 60 * Lock lock = ...; 61 * if (lock.tryLock(50L, TimeUnit.SECONDS)) ... 62 * </pre> 63 * 64 * Note however, that there is no guarantee that a particular timeout 65 * implementation will be able to notice the passage of time at the 66 * same granularity as the given <tt>TimeUnit</tt>. 67 * 68 * @since 1.5 69 * @author Doug Lea 70 */ 71public enum TimeUnit { 72 NANOSECONDS { 73 public long toNanos(long d) { return d; } 74 public long toMicros(long d) { return d/(C1/C0); } 75 public long toMillis(long d) { return d/(C2/C0); } 76 public long toSeconds(long d) { return d/(C3/C0); } 77 public long toMinutes(long d) { return d/(C4/C0); } 78 public long toHours(long d) { return d/(C5/C0); } 79 public long toDays(long d) { return d/(C6/C0); } 80 public long convert(long d, TimeUnit u) { return u.toNanos(d); } 81 int excessNanos(long d, long m) { return (int)(d - (m*C2)); } 82 }, 83 MICROSECONDS { 84 public long toNanos(long d) { return x(d, C1/C0, MAX/(C1/C0)); } 85 public long toMicros(long d) { return d; } 86 public long toMillis(long d) { return d/(C2/C1); } 87 public long toSeconds(long d) { return d/(C3/C1); } 88 public long toMinutes(long d) { return d/(C4/C1); } 89 public long toHours(long d) { return d/(C5/C1); } 90 public long toDays(long d) { return d/(C6/C1); } 91 public long convert(long d, TimeUnit u) { return u.toMicros(d); } 92 int excessNanos(long d, long m) { return (int)((d*C1) - (m*C2)); } 93 }, 94 MILLISECONDS { 95 public long toNanos(long d) { return x(d, C2/C0, MAX/(C2/C0)); } 96 public long toMicros(long d) { return x(d, C2/C1, MAX/(C2/C1)); } 97 public long toMillis(long d) { return d; } 98 public long toSeconds(long d) { return d/(C3/C2); } 99 public long toMinutes(long d) { return d/(C4/C2); } 100 public long toHours(long d) { return d/(C5/C2); } 101 public long toDays(long d) { return d/(C6/C2); } 102 public long convert(long d, TimeUnit u) { return u.toMillis(d); } 103 int excessNanos(long d, long m) { return 0; } 104 }, 105 SECONDS { 106 public long toNanos(long d) { return x(d, C3/C0, MAX/(C3/C0)); } 107 public long toMicros(long d) { return x(d, C3/C1, MAX/(C3/C1)); } 108 public long toMillis(long d) { return x(d, C3/C2, MAX/(C3/C2)); } 109 public long toSeconds(long d) { return d; } 110 public long toMinutes(long d) { return d/(C4/C3); } 111 public long toHours(long d) { return d/(C5/C3); } 112 public long toDays(long d) { return d/(C6/C3); } 113 public long convert(long d, TimeUnit u) { return u.toSeconds(d); } 114 int excessNanos(long d, long m) { return 0; } 115 }, 116 MINUTES { 117 public long toNanos(long d) { return x(d, C4/C0, MAX/(C4/C0)); } 118 public long toMicros(long d) { return x(d, C4/C1, MAX/(C4/C1)); } 119 public long toMillis(long d) { return x(d, C4/C2, MAX/(C4/C2)); } 120 public long toSeconds(long d) { return x(d, C4/C3, MAX/(C4/C3)); } 121 public long toMinutes(long d) { return d; } 122 public long toHours(long d) { return d/(C5/C4); } 123 public long toDays(long d) { return d/(C6/C4); } 124 public long convert(long d, TimeUnit u) { return u.toMinutes(d); } 125 int excessNanos(long d, long m) { return 0; } 126 }, 127 HOURS { 128 public long toNanos(long d) { return x(d, C5/C0, MAX/(C5/C0)); } 129 public long toMicros(long d) { return x(d, C5/C1, MAX/(C5/C1)); } 130 public long toMillis(long d) { return x(d, C5/C2, MAX/(C5/C2)); } 131 public long toSeconds(long d) { return x(d, C5/C3, MAX/(C5/C3)); } 132 public long toMinutes(long d) { return x(d, C5/C4, MAX/(C5/C4)); } 133 public long toHours(long d) { return d; } 134 public long toDays(long d) { return d/(C6/C5); } 135 public long convert(long d, TimeUnit u) { return u.toHours(d); } 136 int excessNanos(long d, long m) { return 0; } 137 }, 138 DAYS { 139 public long toNanos(long d) { return x(d, C6/C0, MAX/(C6/C0)); } 140 public long toMicros(long d) { return x(d, C6/C1, MAX/(C6/C1)); } 141 public long toMillis(long d) { return x(d, C6/C2, MAX/(C6/C2)); } 142 public long toSeconds(long d) { return x(d, C6/C3, MAX/(C6/C3)); } 143 public long toMinutes(long d) { return x(d, C6/C4, MAX/(C6/C4)); } 144 public long toHours(long d) { return x(d, C6/C5, MAX/(C6/C5)); } 145 public long toDays(long d) { return d; } 146 public long convert(long d, TimeUnit u) { return u.toDays(d); } 147 int excessNanos(long d, long m) { return 0; } 148 }; 149 150 // Handy constants for conversion methods 151 static final long C0 = 1L; 152 static final long C1 = C0 * 1000L; 153 static final long C2 = C1 * 1000L; 154 static final long C3 = C2 * 1000L; 155 static final long C4 = C3 * 60L; 156 static final long C5 = C4 * 60L; 157 static final long C6 = C5 * 24L; 158 159 static final long MAX = Long.MAX_VALUE; 160 161 /** 162 * Scale d by m, checking for overflow. 163 * This has a short name to make above code more readable. 164 */ 165 static long x(long d, long m, long over) { 166 if (d > over) return Long.MAX_VALUE; 167 if (d < -over) return Long.MIN_VALUE; 168 return d * m; 169 } 170 171 // To maintain full signature compatibility with 1.5, and to improve the 172 // clarity of the generated javadoc (see 6287639: Abstract methods in 173 // enum classes should not be listed as abstract), method convert 174 // etc. are not declared abstract but otherwise act as abstract methods. 175 176 /** 177 * Convert the given time duration in the given unit to this 178 * unit. Conversions from finer to coarser granularities 179 * truncate, so lose precision. For example converting 180 * <tt>999</tt> milliseconds to seconds results in 181 * <tt>0</tt>. Conversions from coarser to finer granularities 182 * with arguments that would numerically overflow saturate to 183 * <tt>Long.MIN_VALUE</tt> if negative or <tt>Long.MAX_VALUE</tt> 184 * if positive. 185 * 186 * <p>For example, to convert 10 minutes to milliseconds, use: 187 * <tt>TimeUnit.MILLISECONDS.convert(10L, TimeUnit.MINUTES)</tt> 188 * 189 * @param sourceDuration the time duration in the given <tt>sourceUnit</tt> 190 * @param sourceUnit the unit of the <tt>sourceDuration</tt> argument 191 * @return the converted duration in this unit, 192 * or <tt>Long.MIN_VALUE</tt> if conversion would negatively 193 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow. 194 */ 195 public long convert(long sourceDuration, TimeUnit sourceUnit) { 196 throw new AbstractMethodError(); 197 } 198 199 /** 200 * Equivalent to <tt>NANOSECONDS.convert(duration, this)</tt>. 201 * @param duration the duration 202 * @return the converted duration, 203 * or <tt>Long.MIN_VALUE</tt> if conversion would negatively 204 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow. 205 * @see #convert 206 */ 207 public long toNanos(long duration) { 208 throw new AbstractMethodError(); 209 } 210 211 /** 212 * Equivalent to <tt>MICROSECONDS.convert(duration, this)</tt>. 213 * @param duration the duration 214 * @return the converted duration, 215 * or <tt>Long.MIN_VALUE</tt> if conversion would negatively 216 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow. 217 * @see #convert 218 */ 219 public long toMicros(long duration) { 220 throw new AbstractMethodError(); 221 } 222 223 /** 224 * Equivalent to <tt>MILLISECONDS.convert(duration, this)</tt>. 225 * @param duration the duration 226 * @return the converted duration, 227 * or <tt>Long.MIN_VALUE</tt> if conversion would negatively 228 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow. 229 * @see #convert 230 */ 231 public long toMillis(long duration) { 232 throw new AbstractMethodError(); 233 } 234 235 /** 236 * Equivalent to <tt>SECONDS.convert(duration, this)</tt>. 237 * @param duration the duration 238 * @return the converted duration, 239 * or <tt>Long.MIN_VALUE</tt> if conversion would negatively 240 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow. 241 * @see #convert 242 */ 243 public long toSeconds(long duration) { 244 throw new AbstractMethodError(); 245 } 246 247 /** 248 * Equivalent to <tt>MINUTES.convert(duration, this)</tt>. 249 * @param duration the duration 250 * @return the converted duration, 251 * or <tt>Long.MIN_VALUE</tt> if conversion would negatively 252 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow. 253 * @see #convert 254 * @since 1.6 255 */ 256 public long toMinutes(long duration) { 257 throw new AbstractMethodError(); 258 } 259 260 /** 261 * Equivalent to <tt>HOURS.convert(duration, this)</tt>. 262 * @param duration the duration 263 * @return the converted duration, 264 * or <tt>Long.MIN_VALUE</tt> if conversion would negatively 265 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow. 266 * @see #convert 267 * @since 1.6 268 */ 269 public long toHours(long duration) { 270 throw new AbstractMethodError(); 271 } 272 273 /** 274 * Equivalent to <tt>DAYS.convert(duration, this)</tt>. 275 * @param duration the duration 276 * @return the converted duration 277 * @see #convert 278 * @since 1.6 279 */ 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 */ 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 <tt>Object.wait</tt> method. 298 * 299 * <p>For example, you could implement a blocking <tt>poll</tt> 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 */ 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 <tt>Thread.join</tt> 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 */ 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 <tt>Thread.sleep</tt> 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 */ 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