• 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/licenses/publicdomain
5  */
6 
7 package java.util.concurrent;
8 
9 /**
10  * A <tt>TimeUnit</tt> 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  * <tt>TimeUnit</tt> 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 <tt>TimeUnit</tt> 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>  Lock lock = ...;
27  *  if (lock.tryLock(50L, TimeUnit.MILLISECONDS)) ...
28  * </pre>
29  * while this code will timeout in 50 seconds:
30  * <pre>
31  *  Lock lock = ...;
32  *  if (lock.tryLock(50L, TimeUnit.SECONDS)) ...
33  * </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 <tt>TimeUnit</tt>.
38  *
39  * @since 1.5
40  * @author Doug Lea
41  */
42 public enum TimeUnit {
43     NANOSECONDS {
toNanos(long d)44         public long toNanos(long d)   { return d; }
toMicros(long d)45         public long toMicros(long d)  { return d/(C1/C0); }
toMillis(long d)46         public long toMillis(long d)  { return d/(C2/C0); }
toSeconds(long d)47         public long toSeconds(long d) { return d/(C3/C0); }
toMinutes(long d)48         public long toMinutes(long d) { return d/(C4/C0); }
toHours(long d)49         public long toHours(long d)   { return d/(C5/C0); }
toDays(long d)50         public long toDays(long d)    { return d/(C6/C0); }
convert(long d, TimeUnit u)51         public long convert(long d, TimeUnit u) { return u.toNanos(d); }
excessNanos(long d, long m)52         int excessNanos(long d, long m) { return (int)(d - (m*C2)); }
53     },
54     MICROSECONDS {
toNanos(long d)55         public long toNanos(long d)   { return x(d, C1/C0, MAX/(C1/C0)); }
toMicros(long d)56         public long toMicros(long d)  { return d; }
toMillis(long d)57         public long toMillis(long d)  { return d/(C2/C1); }
toSeconds(long d)58         public long toSeconds(long d) { return d/(C3/C1); }
toMinutes(long d)59         public long toMinutes(long d) { return d/(C4/C1); }
toHours(long d)60         public long toHours(long d)   { return d/(C5/C1); }
toDays(long d)61         public long toDays(long d)    { return d/(C6/C1); }
convert(long d, TimeUnit u)62         public long convert(long d, TimeUnit u) { return u.toMicros(d); }
excessNanos(long d, long m)63         int excessNanos(long d, long m) { return (int)((d*C1) - (m*C2)); }
64     },
65     MILLISECONDS {
toNanos(long d)66         public long toNanos(long d)   { return x(d, C2/C0, MAX/(C2/C0)); }
toMicros(long d)67         public long toMicros(long d)  { return x(d, C2/C1, MAX/(C2/C1)); }
toMillis(long d)68         public long toMillis(long d)  { return d; }
toSeconds(long d)69         public long toSeconds(long d) { return d/(C3/C2); }
toMinutes(long d)70         public long toMinutes(long d) { return d/(C4/C2); }
toHours(long d)71         public long toHours(long d)   { return d/(C5/C2); }
toDays(long d)72         public long toDays(long d)    { return d/(C6/C2); }
convert(long d, TimeUnit u)73         public long convert(long d, TimeUnit u) { return u.toMillis(d); }
excessNanos(long d, long m)74         int excessNanos(long d, long m) { return 0; }
75     },
76     SECONDS {
toNanos(long d)77         public long toNanos(long d)   { return x(d, C3/C0, MAX/(C3/C0)); }
toMicros(long d)78         public long toMicros(long d)  { return x(d, C3/C1, MAX/(C3/C1)); }
toMillis(long d)79         public long toMillis(long d)  { return x(d, C3/C2, MAX/(C3/C2)); }
toSeconds(long d)80         public long toSeconds(long d) { return d; }
toMinutes(long d)81         public long toMinutes(long d) { return d/(C4/C3); }
toHours(long d)82         public long toHours(long d)   { return d/(C5/C3); }
toDays(long d)83         public long toDays(long d)    { return d/(C6/C3); }
convert(long d, TimeUnit u)84         public long convert(long d, TimeUnit u) { return u.toSeconds(d); }
excessNanos(long d, long m)85         int excessNanos(long d, long m) { return 0; }
86     },
87     MINUTES {
toNanos(long d)88         public long toNanos(long d)   { return x(d, C4/C0, MAX/(C4/C0)); }
toMicros(long d)89         public long toMicros(long d)  { return x(d, C4/C1, MAX/(C4/C1)); }
toMillis(long d)90         public long toMillis(long d)  { return x(d, C4/C2, MAX/(C4/C2)); }
toSeconds(long d)91         public long toSeconds(long d) { return x(d, C4/C3, MAX/(C4/C3)); }
toMinutes(long d)92         public long toMinutes(long d) { return d; }
toHours(long d)93         public long toHours(long d)   { return d/(C5/C4); }
toDays(long d)94         public long toDays(long d)    { return d/(C6/C4); }
convert(long d, TimeUnit u)95         public long convert(long d, TimeUnit u) { return u.toMinutes(d); }
excessNanos(long d, long m)96         int excessNanos(long d, long m) { return 0; }
97     },
98     HOURS {
toNanos(long d)99         public long toNanos(long d)   { return x(d, C5/C0, MAX/(C5/C0)); }
toMicros(long d)100         public long toMicros(long d)  { return x(d, C5/C1, MAX/(C5/C1)); }
toMillis(long d)101         public long toMillis(long d)  { return x(d, C5/C2, MAX/(C5/C2)); }
toSeconds(long d)102         public long toSeconds(long d) { return x(d, C5/C3, MAX/(C5/C3)); }
toMinutes(long d)103         public long toMinutes(long d) { return x(d, C5/C4, MAX/(C5/C4)); }
toHours(long d)104         public long toHours(long d)   { return d; }
toDays(long d)105         public long toDays(long d)    { return d/(C6/C5); }
convert(long d, TimeUnit u)106         public long convert(long d, TimeUnit u) { return u.toHours(d); }
excessNanos(long d, long m)107         int excessNanos(long d, long m) { return 0; }
108     },
109     DAYS {
toNanos(long d)110         public long toNanos(long d)   { return x(d, C6/C0, MAX/(C6/C0)); }
toMicros(long d)111         public long toMicros(long d)  { return x(d, C6/C1, MAX/(C6/C1)); }
toMillis(long d)112         public long toMillis(long d)  { return x(d, C6/C2, MAX/(C6/C2)); }
toSeconds(long d)113         public long toSeconds(long d) { return x(d, C6/C3, MAX/(C6/C3)); }
toMinutes(long d)114         public long toMinutes(long d) { return x(d, C6/C4, MAX/(C6/C4)); }
toHours(long d)115         public long toHours(long d)   { return x(d, C6/C5, MAX/(C6/C5)); }
toDays(long d)116         public long toDays(long d)    { return d; }
convert(long d, TimeUnit u)117         public long convert(long d, TimeUnit u) { return u.toDays(d); }
excessNanos(long d, long m)118         int excessNanos(long d, long m) { return 0; }
119     };
120 
121     // Handy constants for conversion methods
122     static final long C0 = 1L;
123     static final long C1 = C0 * 1000L;
124     static final long C2 = C1 * 1000L;
125     static final long C3 = C2 * 1000L;
126     static final long C4 = C3 * 60L;
127     static final long C5 = C4 * 60L;
128     static final long C6 = C5 * 24L;
129 
130     static final long MAX = Long.MAX_VALUE;
131 
132     /**
133      * Scale d by m, checking for overflow.
134      * This has a short name to make above code more readable.
135      */
x(long d, long m, long over)136     static long x(long d, long m, long over) {
137         if (d >  over) return Long.MAX_VALUE;
138         if (d < -over) return Long.MIN_VALUE;
139         return d * m;
140     }
141 
142     // To maintain full signature compatibility with 1.5, and to improve the
143     // clarity of the generated javadoc (see 6287639: Abstract methods in
144     // enum classes should not be listed as abstract), method convert
145     // etc. are not declared abstract but otherwise act as abstract methods.
146 
147     /**
148      * Convert the given time duration in the given unit to this
149      * unit.  Conversions from finer to coarser granularities
150      * truncate, so lose precision. For example converting
151      * <tt>999</tt> milliseconds to seconds results in
152      * <tt>0</tt>. Conversions from coarser to finer granularities
153      * with arguments that would numerically overflow saturate to
154      * <tt>Long.MIN_VALUE</tt> if negative or <tt>Long.MAX_VALUE</tt>
155      * if positive.
156      *
157      * <p>For example, to convert 10 minutes to milliseconds, use:
158      * <tt>TimeUnit.MILLISECONDS.convert(10L, TimeUnit.MINUTES)</tt>
159      *
160      * @param sourceDuration the time duration in the given <tt>sourceUnit</tt>
161      * @param sourceUnit the unit of the <tt>sourceDuration</tt> argument
162      * @return the converted duration in this unit,
163      * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
164      * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
165      */
convert(long sourceDuration, TimeUnit sourceUnit)166     public long convert(long sourceDuration, TimeUnit sourceUnit) {
167         throw new AbstractMethodError();
168     }
169 
170     /**
171      * Equivalent to <tt>NANOSECONDS.convert(duration, this)</tt>.
172      * @param duration the duration
173      * @return the converted duration,
174      * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
175      * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
176      * @see #convert
177      */
toNanos(long duration)178     public long toNanos(long duration) {
179         throw new AbstractMethodError();
180     }
181 
182     /**
183      * Equivalent to <tt>MICROSECONDS.convert(duration, this)</tt>.
184      * @param duration the duration
185      * @return the converted duration,
186      * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
187      * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
188      * @see #convert
189      */
toMicros(long duration)190     public long toMicros(long duration) {
191         throw new AbstractMethodError();
192     }
193 
194     /**
195      * Equivalent to <tt>MILLISECONDS.convert(duration, this)</tt>.
196      * @param duration the duration
197      * @return the converted duration,
198      * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
199      * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
200      * @see #convert
201      */
toMillis(long duration)202     public long toMillis(long duration) {
203         throw new AbstractMethodError();
204     }
205 
206     /**
207      * Equivalent to <tt>SECONDS.convert(duration, this)</tt>.
208      * @param duration the duration
209      * @return the converted duration,
210      * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
211      * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
212      * @see #convert
213      */
toSeconds(long duration)214     public long toSeconds(long duration) {
215         throw new AbstractMethodError();
216     }
217 
218     /**
219      * Equivalent to <tt>MINUTES.convert(duration, this)</tt>.
220      * @param duration the duration
221      * @return the converted duration,
222      * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
223      * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
224      * @see #convert
225      * @since 1.6
226      */
toMinutes(long duration)227     public long toMinutes(long duration) {
228         throw new AbstractMethodError();
229     }
230 
231     /**
232      * Equivalent to <tt>HOURS.convert(duration, this)</tt>.
233      * @param duration the duration
234      * @return the converted duration,
235      * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
236      * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
237      * @see #convert
238      * @since 1.6
239      */
toHours(long duration)240     public long toHours(long duration) {
241         throw new AbstractMethodError();
242     }
243 
244     /**
245      * Equivalent to <tt>DAYS.convert(duration, this)</tt>.
246      * @param duration the duration
247      * @return the converted duration
248      * @see #convert
249      * @since 1.6
250      */
toDays(long duration)251     public long toDays(long duration) {
252         throw new AbstractMethodError();
253     }
254 
255     /**
256      * Utility to compute the excess-nanosecond argument to wait,
257      * sleep, join.
258      * @param d the duration
259      * @param m the number of milliseconds
260      * @return the number of nanoseconds
261      */
excessNanos(long d, long m)262     abstract int excessNanos(long d, long m);
263 
264     /**
265      * Performs a timed {@link Object#wait(long, int) Object.wait}
266      * using this time unit.
267      * This is a convenience method that converts timeout arguments
268      * into the form required by the <tt>Object.wait</tt> method.
269      *
270      * <p>For example, you could implement a blocking <tt>poll</tt>
271      * method (see {@link BlockingQueue#poll BlockingQueue.poll})
272      * using:
273      *
274      *  <pre> {@code
275      * public synchronized Object poll(long timeout, TimeUnit unit)
276      *     throws InterruptedException {
277      *   while (empty) {
278      *     unit.timedWait(this, timeout);
279      *     ...
280      *   }
281      * }}</pre>
282      *
283      * @param obj the object to wait on
284      * @param timeout the maximum time to wait. If less than
285      * or equal to zero, do not wait at all.
286      * @throws InterruptedException if interrupted while waiting
287      */
timedWait(Object obj, long timeout)288     public void timedWait(Object obj, long timeout)
289             throws InterruptedException {
290         if (timeout > 0) {
291             long ms = toMillis(timeout);
292             int ns = excessNanos(timeout, ms);
293             obj.wait(ms, ns);
294         }
295     }
296 
297     /**
298      * Performs a timed {@link Thread#join(long, int) Thread.join}
299      * using this time unit.
300      * This is a convenience method that converts time arguments into the
301      * form required by the <tt>Thread.join</tt> method.
302      *
303      * @param thread the thread to wait for
304      * @param timeout the maximum time to wait. If less than
305      * or equal to zero, do not wait at all.
306      * @throws InterruptedException if interrupted while waiting
307      */
timedJoin(Thread thread, long timeout)308     public void timedJoin(Thread thread, long timeout)
309             throws InterruptedException {
310         if (timeout > 0) {
311             long ms = toMillis(timeout);
312             int ns = excessNanos(timeout, ms);
313             thread.join(ms, ns);
314         }
315     }
316 
317     /**
318      * Performs a {@link Thread#sleep(long, int) Thread.sleep} using
319      * this time unit.
320      * This is a convenience method that converts time arguments into the
321      * form required by the <tt>Thread.sleep</tt> method.
322      *
323      * @param timeout the minimum time to sleep. If less than
324      * or equal to zero, do not sleep at all.
325      * @throws InterruptedException if interrupted while sleeping
326      */
sleep(long timeout)327     public void sleep(long timeout) throws InterruptedException {
328         if (timeout > 0) {
329             long ms = toMillis(timeout);
330             int ns = excessNanos(timeout, ms);
331             Thread.sleep(ms, ns);
332         }
333     }
334 
335 }
336