ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/TimeUnit.java
Revision: 1.49
Committed: Wed Mar 23 14:03:06 2016 UTC (8 years, 2 months ago) by dl
Branch: MAIN
Changes since 1.48: +75 -118 lines
Log Message:
Avoid megamorphic dispatch

File Contents

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