ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/TimeUnit.java
Revision: 1.51
Committed: Fri Mar 25 03:14:56 2016 UTC (8 years, 2 months ago) by jsr166
Branch: MAIN
Changes since 1.50: +3 -2 lines
Log Message:
coding style

File Contents

# Content
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.time.temporal.ChronoUnit;
10 import java.util.Objects;
11
12 /**
13 * A {@code TimeUnit} represents time durations at a given unit of
14 * granularity and provides utility methods to convert across units,
15 * and to perform timing and delay operations in these units. A
16 * {@code TimeUnit} does not maintain time information, but only
17 * 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 * <p>A {@code TimeUnit} is mainly used to inform time-based methods
25 * 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 * <pre> {@code
30 * Lock lock = ...;
31 * if (lock.tryLock(50L, TimeUnit.MILLISECONDS)) ...}</pre>
32 *
33 * while this code will timeout in 50 seconds:
34 * <pre> {@code
35 * Lock lock = ...;
36 * if (lock.tryLock(50L, TimeUnit.SECONDS)) ...}</pre>
37 *
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 * same granularity as the given {@code TimeUnit}.
41 *
42 * @since 1.5
43 * @author Doug Lea
44 */
45 public enum TimeUnit {
46 /**
47 * Time unit representing one thousandth of a microsecond.
48 */
49 NANOSECONDS(1L), // (cannot use symbolic scale names here)
50 /**
51 * Time unit representing one thousandth of a millisecond.
52 */
53 MICROSECONDS(1000L),
54 /**
55 * Time unit representing one thousandth of a second.
56 */
57 MILLISECONDS(1000L * 1000L),
58 /**
59 * Time unit representing one second.
60 */
61 SECONDS(1000L * 1000L * 1000L),
62 /**
63 * Time unit representing sixty seconds.
64 * @since 1.6
65 */
66 MINUTES(1000L * 1000L * 1000L * 60L),
67 /**
68 * Time unit representing sixty minutes.
69 * @since 1.6
70 */
71 HOURS(1000L * 1000L * 1000L * 60L * 60L),
72 /**
73 * Time unit representing twenty four hours.
74 * @since 1.6
75 */
76 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)
102 ? scale / MILLI_SCALE
103 : MILLI_SCALE / scale;
104 this.millisRatio = r;
105 this.maxMillis = Long.MAX_VALUE / r;
106 }
107
108 /**
109 * General conversion utility.
110 *
111 * @param d duration
112 * @param dst result scale unit
113 * @param src source scale unit
114 */
115 private static long cvt(long d, long dst, long src) {
116 long r, m;
117 if (src == dst)
118 return d;
119 else if (src < dst)
120 return d / (dst / src);
121 else if (d > (m = Long.MAX_VALUE / (r = src / dst)))
122 return Long.MAX_VALUE;
123 else if (d < -m)
124 return Long.MIN_VALUE;
125 else
126 return d * r;
127 }
128
129 /**
130 * Converts the given time duration in the given unit to this unit.
131 * Conversions from finer to coarser granularities truncate, so
132 * lose precision. For example, converting {@code 999} milliseconds
133 * to seconds results in {@code 0}. Conversions from coarser to
134 * finer granularities with arguments that would numerically
135 * overflow saturate to {@code Long.MIN_VALUE} if negative or
136 * {@code Long.MAX_VALUE} if positive.
137 *
138 * <p>For example, to convert 10 minutes to milliseconds, use:
139 * {@code TimeUnit.MILLISECONDS.convert(10L, TimeUnit.MINUTES)}
140 *
141 * @param sourceDuration the time duration in the given {@code sourceUnit}
142 * @param sourceUnit the unit of the {@code sourceDuration} argument
143 * @return the converted duration in this unit,
144 * or {@code Long.MIN_VALUE} if conversion would negatively
145 * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
146 */
147 public long convert(long sourceDuration, TimeUnit sourceUnit) {
148 return cvt(sourceDuration, scale, sourceUnit.scale);
149 }
150
151 /**
152 * Equivalent to
153 * {@link #convert(long, TimeUnit) NANOSECONDS.convert(duration, this)}.
154 * @param duration the duration
155 * @return the converted duration,
156 * or {@code Long.MIN_VALUE} if conversion would negatively
157 * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
158 */
159 public long toNanos(long duration) {
160 long s, m;
161 if ((s = scale) == NANO_SCALE)
162 return duration;
163 else if (duration > (m = maxNanos))
164 return Long.MAX_VALUE;
165 else if (duration < -m)
166 return Long.MIN_VALUE;
167 else
168 return duration * s;
169 }
170
171 /**
172 * Equivalent to
173 * {@link #convert(long, TimeUnit) MICROSECONDS.convert(duration, this)}.
174 * @param duration the duration
175 * @return the converted duration,
176 * or {@code Long.MIN_VALUE} if conversion would negatively
177 * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
178 */
179 public long toMicros(long duration) {
180 return cvt(duration, MICRO_SCALE, scale);
181 }
182
183 /**
184 * Equivalent to
185 * {@link #convert(long, TimeUnit) MILLISECONDS.convert(duration, this)}.
186 * @param duration the duration
187 * @return the converted duration,
188 * or {@code Long.MIN_VALUE} if conversion would negatively
189 * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
190 */
191 public long toMillis(long duration) {
192 long s, m;
193 if ((s = scale) == MILLI_SCALE)
194 return duration;
195 else if (s < MILLI_SCALE)
196 return duration / millisRatio;
197 else if (duration > (m = maxMillis))
198 return Long.MAX_VALUE;
199 else if (duration < -m)
200 return Long.MIN_VALUE;
201 else
202 return duration * millisRatio;
203 }
204
205 /**
206 * Equivalent to
207 * {@link #convert(long, TimeUnit) SECONDS.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 */
213 public long toSeconds(long duration) {
214 return cvt(duration, SECOND_SCALE, scale);
215 }
216
217 /**
218 * Equivalent to
219 * {@link #convert(long, TimeUnit) MINUTES.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 * @since 1.6
225 */
226 public long toMinutes(long duration) {
227 return cvt(duration, MINUTE_SCALE, scale);
228 }
229
230 /**
231 * Equivalent to
232 * {@link #convert(long, TimeUnit) HOURS.convert(duration, this)}.
233 * @param duration the duration
234 * @return the converted duration,
235 * or {@code Long.MIN_VALUE} if conversion would negatively
236 * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
237 * @since 1.6
238 */
239 public long toHours(long duration) {
240 return cvt(duration, HOUR_SCALE, scale);
241 }
242
243 /**
244 * Equivalent to
245 * {@link #convert(long, TimeUnit) DAYS.convert(duration, this)}.
246 * @param duration the duration
247 * @return the converted duration
248 * @since 1.6
249 */
250 public long toDays(long duration) {
251 return cvt(duration, DAY_SCALE, scale);
252 }
253
254 /**
255 * Utility to compute the excess-nanosecond argument to wait,
256 * sleep, join.
257 * @param d the duration
258 * @param m the number of milliseconds
259 * @return the number of nanoseconds
260 */
261 private int excessNanos(long d, long m) {
262 long s;
263 if ((s = scale) == NANO_SCALE)
264 return (int)(d - (m * MILLI_SCALE));
265 else if (s == MICRO_SCALE)
266 return (int)((d * 1000L) - (m * MILLI_SCALE));
267 else
268 return 0;
269 }
270
271 /**
272 * Performs a timed {@link Object#wait(long, int) Object.wait}
273 * using this time unit.
274 * This is a convenience method that converts timeout arguments
275 * into the form required by the {@code Object.wait} method.
276 *
277 * <p>For example, you could implement a blocking {@code poll}
278 * method (see {@link BlockingQueue#poll BlockingQueue.poll})
279 * using:
280 *
281 * <pre> {@code
282 * public synchronized Object poll(long timeout, TimeUnit unit)
283 * throws InterruptedException {
284 * while (empty) {
285 * unit.timedWait(this, timeout);
286 * ...
287 * }
288 * }}</pre>
289 *
290 * @param obj the object to wait on
291 * @param timeout the maximum time to wait. If less than
292 * or equal to zero, do not wait at all.
293 * @throws InterruptedException if interrupted while waiting
294 */
295 public void timedWait(Object obj, long timeout)
296 throws InterruptedException {
297 if (timeout > 0) {
298 long ms = toMillis(timeout);
299 int ns = excessNanos(timeout, ms);
300 obj.wait(ms, ns);
301 }
302 }
303
304 /**
305 * Performs a timed {@link Thread#join(long, int) Thread.join}
306 * using this time unit.
307 * This is a convenience method that converts time arguments into the
308 * form required by the {@code Thread.join} method.
309 *
310 * @param thread the thread to wait for
311 * @param timeout the maximum time to wait. If less than
312 * or equal to zero, do not wait at all.
313 * @throws InterruptedException if interrupted while waiting
314 */
315 public void timedJoin(Thread thread, long timeout)
316 throws InterruptedException {
317 if (timeout > 0) {
318 long ms = toMillis(timeout);
319 int ns = excessNanos(timeout, ms);
320 thread.join(ms, ns);
321 }
322 }
323
324 /**
325 * Performs a {@link Thread#sleep(long, int) Thread.sleep} using
326 * this time unit.
327 * This is a convenience method that converts time arguments into the
328 * form required by the {@code Thread.sleep} method.
329 *
330 * @param timeout the minimum time to sleep. If less than
331 * or equal to zero, do not sleep at all.
332 * @throws InterruptedException if interrupted while sleeping
333 */
334 public void sleep(long timeout) throws InterruptedException {
335 if (timeout > 0) {
336 long ms = toMillis(timeout);
337 int ns = excessNanos(timeout, ms);
338 Thread.sleep(ms, ns);
339 }
340 }
341
342 /**
343 * Converts this {@code TimeUnit} to the equivalent {@code ChronoUnit}.
344 *
345 * @return the converted equivalent ChronoUnit
346 * @since 9
347 */
348 public ChronoUnit toChronoUnit() {
349 switch (this) {
350 case NANOSECONDS: return ChronoUnit.NANOS;
351 case MICROSECONDS: return ChronoUnit.MICROS;
352 case MILLISECONDS: return ChronoUnit.MILLIS;
353 case SECONDS: return ChronoUnit.SECONDS;
354 case MINUTES: return ChronoUnit.MINUTES;
355 case HOURS: return ChronoUnit.HOURS;
356 case DAYS: return ChronoUnit.DAYS;
357 default: throw new AssertionError();
358 }
359 }
360
361 /**
362 * Converts a {@code ChronoUnit} to the equivalent {@code TimeUnit}.
363 *
364 * @param chronoUnit the ChronoUnit to convert
365 * @return the converted equivalent TimeUnit
366 * @throws IllegalArgumentException if {@code chronoUnit} has no
367 * equivalent TimeUnit
368 * @throws NullPointerException if {@code chronoUnit} is null
369 * @since 9
370 */
371 public static TimeUnit of(ChronoUnit chronoUnit) {
372 switch (Objects.requireNonNull(chronoUnit, "chronoUnit")) {
373 case NANOS: return TimeUnit.NANOSECONDS;
374 case MICROS: return TimeUnit.MICROSECONDS;
375 case MILLIS: return TimeUnit.MILLISECONDS;
376 case SECONDS: return TimeUnit.SECONDS;
377 case MINUTES: return TimeUnit.MINUTES;
378 case HOURS: return TimeUnit.HOURS;
379 case DAYS: return TimeUnit.DAYS;
380 default:
381 throw new IllegalArgumentException(
382 "No TimeUnit equivalent for " + chronoUnit);
383 }
384 }
385
386 }