ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jdk8/java/util/concurrent/TimeUnit.java
Revision: 1.2
Committed: Sat Mar 26 12:02:03 2016 UTC (8 years, 2 months ago) by dl
Branch: MAIN
Changes since 1.1: +32 -16 lines
Log Message:
use jdk8 @Contended

File Contents

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