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