ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/TimeUnit.java
Revision: 1.52
Committed: Fri Mar 25 16:16:02 2016 UTC (8 years, 2 months ago) by dl
Branch: MAIN
Changes since 1.51: +29 -11 lines
Log Message:
Cache toSeconds conversion constants

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 dl 1.52 * the units most commonly used in conversion results, in methods
90     * toNanos, toMillis and toSeconds. Other cases compute them, in
91     * method cvt.
92 dl 1.49 */
93    
94     private final long scale;
95     private final long maxNanos;
96     private final long maxMillis;
97 dl 1.52 private final long maxSecs;
98     private final int milliRatio;
99     private final int secRatio;
100 dl 1.49
101     TimeUnit(long scale) {
102     this.scale = scale;
103     this.maxNanos = Long.MAX_VALUE / scale;
104 dl 1.52 long mr = (scale >= MILLI_SCALE)
105     ? (scale / MILLI_SCALE)
106     : (MILLI_SCALE / scale);
107     this.milliRatio = (int)mr;
108     this.maxMillis = Long.MAX_VALUE / mr;
109     long sr = (scale >= SECOND_SCALE)
110     ? (scale / SECOND_SCALE)
111     : (SECOND_SCALE / scale);
112     this.secRatio = (int)sr;
113     this.maxSecs = Long.MAX_VALUE / sr;
114 dl 1.49 }
115    
116     /**
117     * General conversion utility.
118     *
119     * @param d duration
120     * @param dst result scale unit
121     * @param src source scale unit
122     */
123     private static long cvt(long d, long dst, long src) {
124     long r, m;
125 dl 1.50 if (src == dst)
126     return d;
127     else if (src < dst)
128     return d / (dst / src);
129     else if (d > (m = Long.MAX_VALUE / (r = src / dst)))
130     return Long.MAX_VALUE;
131     else if (d < -m)
132     return Long.MIN_VALUE;
133     else
134     return d * r;
135 dl 1.49 }
136 dl 1.32
137 dl 1.27 /**
138 jsr166 1.42 * Converts the given time duration in the given unit to this unit.
139     * Conversions from finer to coarser granularities truncate, so
140     * lose precision. For example, converting {@code 999} milliseconds
141     * to seconds results in {@code 0}. Conversions from coarser to
142     * finer granularities with arguments that would numerically
143     * overflow saturate to {@code Long.MIN_VALUE} if negative or
144     * {@code Long.MAX_VALUE} if positive.
145 jsr166 1.33 *
146     * <p>For example, to convert 10 minutes to milliseconds, use:
147 jsr166 1.40 * {@code TimeUnit.MILLISECONDS.convert(10L, TimeUnit.MINUTES)}
148 dl 1.27 *
149 jsr166 1.40 * @param sourceDuration the time duration in the given {@code sourceUnit}
150     * @param sourceUnit the unit of the {@code sourceDuration} argument
151 dl 1.27 * @return the converted duration in this unit,
152 jsr166 1.40 * or {@code Long.MIN_VALUE} if conversion would negatively
153     * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
154 dl 1.27 */
155 dl 1.32 public long convert(long sourceDuration, TimeUnit sourceUnit) {
156 dl 1.49 return cvt(sourceDuration, scale, sourceUnit.scale);
157 dl 1.32 }
158 jsr166 1.29
159 dl 1.27 /**
160 jsr166 1.41 * Equivalent to
161     * {@link #convert(long, TimeUnit) NANOSECONDS.convert(duration, this)}.
162 dl 1.27 * @param duration the duration
163     * @return the converted duration,
164 jsr166 1.40 * or {@code Long.MIN_VALUE} if conversion would negatively
165     * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
166 dl 1.27 */
167 dl 1.32 public long toNanos(long duration) {
168 dl 1.49 long s, m;
169 dl 1.50 if ((s = scale) == NANO_SCALE)
170     return duration;
171     else if (duration > (m = maxNanos))
172     return Long.MAX_VALUE;
173     else if (duration < -m)
174     return Long.MIN_VALUE;
175     else
176     return duration * s;
177 dl 1.32 }
178 jsr166 1.29
179 dl 1.27 /**
180 jsr166 1.41 * Equivalent to
181     * {@link #convert(long, TimeUnit) MICROSECONDS.convert(duration, this)}.
182 dl 1.27 * @param duration the duration
183     * @return the converted duration,
184 jsr166 1.40 * or {@code Long.MIN_VALUE} if conversion would negatively
185     * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
186 dl 1.27 */
187 dl 1.32 public long toMicros(long duration) {
188 dl 1.49 return cvt(duration, MICRO_SCALE, scale);
189 dl 1.32 }
190 jsr166 1.29
191 dl 1.27 /**
192 jsr166 1.41 * Equivalent to
193     * {@link #convert(long, TimeUnit) MILLISECONDS.convert(duration, this)}.
194 dl 1.27 * @param duration the duration
195     * @return the converted duration,
196 jsr166 1.40 * or {@code Long.MIN_VALUE} if conversion would negatively
197     * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
198 dl 1.27 */
199 dl 1.32 public long toMillis(long duration) {
200 dl 1.49 long s, m;
201 dl 1.50 if ((s = scale) == MILLI_SCALE)
202     return duration;
203     else if (s < MILLI_SCALE)
204 dl 1.52 return duration / milliRatio;
205 dl 1.50 else if (duration > (m = maxMillis))
206     return Long.MAX_VALUE;
207     else if (duration < -m)
208     return Long.MIN_VALUE;
209     else
210 dl 1.52 return duration * milliRatio;
211 dl 1.32 }
212 jsr166 1.29
213 dl 1.27 /**
214 jsr166 1.41 * Equivalent to
215     * {@link #convert(long, TimeUnit) SECONDS.convert(duration, this)}.
216 dl 1.27 * @param duration the duration
217     * @return the converted duration,
218 jsr166 1.40 * or {@code Long.MIN_VALUE} if conversion would negatively
219     * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
220 dl 1.27 */
221 dl 1.32 public long toSeconds(long duration) {
222 dl 1.52 long s, m;
223     if ((s = scale) == SECOND_SCALE)
224     return duration;
225     else if (s < SECOND_SCALE)
226     return duration / secRatio;
227     else if (duration > (m = maxSecs))
228     return Long.MAX_VALUE;
229     else if (duration < -m)
230     return Long.MIN_VALUE;
231     else
232     return duration * secRatio;
233 dl 1.32 }
234 jsr166 1.29
235 dl 1.27 /**
236 jsr166 1.41 * Equivalent to
237     * {@link #convert(long, TimeUnit) MINUTES.convert(duration, this)}.
238 dl 1.27 * @param duration the duration
239     * @return the converted duration,
240 jsr166 1.40 * or {@code Long.MIN_VALUE} if conversion would negatively
241     * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
242 dl 1.31 * @since 1.6
243 dl 1.27 */
244 dl 1.32 public long toMinutes(long duration) {
245 dl 1.49 return cvt(duration, MINUTE_SCALE, scale);
246 dl 1.32 }
247 jsr166 1.29
248 dl 1.27 /**
249 jsr166 1.41 * Equivalent to
250     * {@link #convert(long, TimeUnit) HOURS.convert(duration, this)}.
251 dl 1.27 * @param duration the duration
252     * @return the converted duration,
253 jsr166 1.40 * or {@code Long.MIN_VALUE} if conversion would negatively
254     * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
255 dl 1.31 * @since 1.6
256 dl 1.27 */
257 dl 1.32 public long toHours(long duration) {
258 dl 1.49 return cvt(duration, HOUR_SCALE, scale);
259 dl 1.32 }
260 jsr166 1.29
261 dl 1.27 /**
262 jsr166 1.41 * Equivalent to
263     * {@link #convert(long, TimeUnit) DAYS.convert(duration, this)}.
264 dl 1.27 * @param duration the duration
265     * @return the converted duration
266 dl 1.31 * @since 1.6
267 dl 1.27 */
268 dl 1.32 public long toDays(long duration) {
269 dl 1.49 return cvt(duration, DAY_SCALE, scale);
270 dl 1.32 }
271 jsr166 1.29
272 dl 1.27 /**
273     * Utility to compute the excess-nanosecond argument to wait,
274     * sleep, join.
275     * @param d the duration
276     * @param m the number of milliseconds
277     * @return the number of nanoseconds
278     */
279 dl 1.49 private int excessNanos(long d, long m) {
280     long s;
281 dl 1.50 if ((s = scale) == NANO_SCALE)
282     return (int)(d - (m * MILLI_SCALE));
283     else if (s == MICRO_SCALE)
284     return (int)((d * 1000L) - (m * MILLI_SCALE));
285     else
286     return 0;
287 dl 1.49 }
288 jsr166 1.29
289 dl 1.27 /**
290 jsr166 1.37 * Performs a timed {@link Object#wait(long, int) Object.wait}
291     * using this time unit.
292 dl 1.27 * This is a convenience method that converts timeout arguments
293 jsr166 1.40 * into the form required by the {@code Object.wait} method.
294 dl 1.27 *
295 jsr166 1.40 * <p>For example, you could implement a blocking {@code poll}
296 dl 1.27 * method (see {@link BlockingQueue#poll BlockingQueue.poll})
297     * using:
298     *
299 jsr166 1.45 * <pre> {@code
300 jsr166 1.36 * public synchronized Object poll(long timeout, TimeUnit unit)
301     * throws InterruptedException {
302     * while (empty) {
303     * unit.timedWait(this, timeout);
304     * ...
305     * }
306     * }}</pre>
307 dl 1.27 *
308     * @param obj the object to wait on
309 dl 1.28 * @param timeout the maximum time to wait. If less than
310     * or equal to zero, do not wait at all.
311 jsr166 1.37 * @throws InterruptedException if interrupted while waiting
312 dl 1.27 */
313     public void timedWait(Object obj, long timeout)
314 jsr166 1.37 throws InterruptedException {
315 dl 1.27 if (timeout > 0) {
316     long ms = toMillis(timeout);
317     int ns = excessNanos(timeout, ms);
318     obj.wait(ms, ns);
319     }
320     }
321 jsr166 1.29
322 dl 1.27 /**
323 jsr166 1.37 * Performs a timed {@link Thread#join(long, int) Thread.join}
324     * using this time unit.
325 dl 1.27 * This is a convenience method that converts time arguments into the
326 jsr166 1.40 * form required by the {@code Thread.join} method.
327 jsr166 1.37 *
328 dl 1.27 * @param thread the thread to wait for
329 dl 1.28 * @param timeout the maximum time to wait. If less than
330     * or equal to zero, do not wait at all.
331 jsr166 1.37 * @throws InterruptedException if interrupted while waiting
332 dl 1.27 */
333     public void timedJoin(Thread thread, long timeout)
334 jsr166 1.37 throws InterruptedException {
335 dl 1.27 if (timeout > 0) {
336     long ms = toMillis(timeout);
337     int ns = excessNanos(timeout, ms);
338     thread.join(ms, ns);
339     }
340     }
341 jsr166 1.29
342 dl 1.27 /**
343 jsr166 1.37 * Performs a {@link Thread#sleep(long, int) Thread.sleep} using
344     * this time unit.
345 dl 1.27 * This is a convenience method that converts time arguments into the
346 jsr166 1.40 * form required by the {@code Thread.sleep} method.
347 jsr166 1.37 *
348 dl 1.28 * @param timeout the minimum time to sleep. If less than
349     * or equal to zero, do not sleep at all.
350 jsr166 1.37 * @throws InterruptedException if interrupted while sleeping
351 dl 1.27 */
352     public void sleep(long timeout) throws InterruptedException {
353     if (timeout > 0) {
354     long ms = toMillis(timeout);
355     int ns = excessNanos(timeout, ms);
356     Thread.sleep(ms, ns);
357     }
358     }
359 jsr166 1.29
360 jsr166 1.48 /**
361     * Converts this {@code TimeUnit} to the equivalent {@code ChronoUnit}.
362     *
363     * @return the converted equivalent ChronoUnit
364     * @since 9
365     */
366     public ChronoUnit toChronoUnit() {
367     switch (this) {
368     case NANOSECONDS: return ChronoUnit.NANOS;
369     case MICROSECONDS: return ChronoUnit.MICROS;
370     case MILLISECONDS: return ChronoUnit.MILLIS;
371     case SECONDS: return ChronoUnit.SECONDS;
372     case MINUTES: return ChronoUnit.MINUTES;
373     case HOURS: return ChronoUnit.HOURS;
374     case DAYS: return ChronoUnit.DAYS;
375     default: throw new AssertionError();
376     }
377     }
378    
379     /**
380     * Converts a {@code ChronoUnit} to the equivalent {@code TimeUnit}.
381     *
382     * @param chronoUnit the ChronoUnit to convert
383     * @return the converted equivalent TimeUnit
384     * @throws IllegalArgumentException if {@code chronoUnit} has no
385     * equivalent TimeUnit
386     * @throws NullPointerException if {@code chronoUnit} is null
387     * @since 9
388     */
389     public static TimeUnit of(ChronoUnit chronoUnit) {
390     switch (Objects.requireNonNull(chronoUnit, "chronoUnit")) {
391     case NANOS: return TimeUnit.NANOSECONDS;
392     case MICROS: return TimeUnit.MICROSECONDS;
393     case MILLIS: return TimeUnit.MILLISECONDS;
394     case SECONDS: return TimeUnit.SECONDS;
395     case MINUTES: return TimeUnit.MINUTES;
396     case HOURS: return TimeUnit.HOURS;
397     case DAYS: return TimeUnit.DAYS;
398     default:
399     throw new IllegalArgumentException(
400     "No TimeUnit equivalent for " + chronoUnit);
401     }
402     }
403    
404 tim 1.1 }