1 /*
2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3  *
4  * This code is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 2 only, as
6  * published by the Free Software Foundation.  Oracle designates this
7  * particular file as subject to the "Classpath" exception as provided
8  * by Oracle in the LICENSE file that accompanied this code.
9  *
10  * This code is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * version 2 for more details (a copy is included in the LICENSE file that
14  * accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License version
17  * 2 along with this work; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19  *
20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21  * or visit www.oracle.com if you need additional information or have any
22  * questions.
23  */
24 
25 /*
26  * This file is available under and governed by the GNU General Public
27  * License version 2 only, as published by the Free Software Foundation.
28  * However, the following notice accompanied the original version of this
29  * file:
30  *
31  * Written by Doug Lea with assistance from members of JCP JSR-166
32  * Expert Group and released to the public domain, as explained at
33  * http://creativecommons.org/publicdomain/zero/1.0/
34  */
35 
36 package java.util.concurrent;
37 
38 import java.util.Objects;
39 
40 // BEGIN android-note
41 // removed java 9 ChronoUnit related code
42 // END android-note
43 
44 /**
45  * A {@code TimeUnit} represents time durations at a given unit of
46  * granularity and provides utility methods to convert across units,
47  * and to perform timing and delay operations in these units.  A
48  * {@code TimeUnit} does not maintain time information, but only
49  * helps organize and use time representations that may be maintained
50  * separately across various contexts.  A nanosecond is defined as one
51  * thousandth of a microsecond, a microsecond as one thousandth of a
52  * millisecond, a millisecond as one thousandth of a second, a minute
53  * as sixty seconds, an hour as sixty minutes, and a day as twenty four
54  * hours.
55  *
56  * <p>A {@code TimeUnit} is mainly used to inform time-based methods
57  * how a given timing parameter should be interpreted. For example,
58  * the following code will timeout in 50 milliseconds if the {@link
59  * java.util.concurrent.locks.Lock lock} is not available:
60  *
61  * <pre> {@code
62  * Lock lock = ...;
63  * if (lock.tryLock(50L, TimeUnit.MILLISECONDS)) ...}</pre>
64  *
65  * while this code will timeout in 50 seconds:
66  * <pre> {@code
67  * Lock lock = ...;
68  * if (lock.tryLock(50L, TimeUnit.SECONDS)) ...}</pre>
69  *
70  * Note however, that there is no guarantee that a particular timeout
71  * implementation will be able to notice the passage of time at the
72  * same granularity as the given {@code TimeUnit}.
73  *
74  * @since 1.5
75  * @author Doug Lea
76  */
77 public enum TimeUnit {
78     /**
79      * Time unit representing one thousandth of a microsecond.
80      */
81     NANOSECONDS {
toNanos(long d)82         public long toNanos(long d)   { return d; }
toMicros(long d)83         public long toMicros(long d)  { return d/(C1/C0); }
toMillis(long d)84         public long toMillis(long d)  { return d/(C2/C0); }
toSeconds(long d)85         public long toSeconds(long d) { return d/(C3/C0); }
toMinutes(long d)86         public long toMinutes(long d) { return d/(C4/C0); }
toHours(long d)87         public long toHours(long d)   { return d/(C5/C0); }
toDays(long d)88         public long toDays(long d)    { return d/(C6/C0); }
convert(long d, TimeUnit u)89         public long convert(long d, TimeUnit u) { return u.toNanos(d); }
excessNanos(long d, long m)90         int excessNanos(long d, long m) { return (int)(d - (m*C2)); }
91     },
92 
93     /**
94      * Time unit representing one thousandth of a millisecond.
95      */
96     MICROSECONDS {
toNanos(long d)97         public long toNanos(long d)   { return x(d, C1/C0, MAX/(C1/C0)); }
toMicros(long d)98         public long toMicros(long d)  { return d; }
toMillis(long d)99         public long toMillis(long d)  { return d/(C2/C1); }
toSeconds(long d)100         public long toSeconds(long d) { return d/(C3/C1); }
toMinutes(long d)101         public long toMinutes(long d) { return d/(C4/C1); }
toHours(long d)102         public long toHours(long d)   { return d/(C5/C1); }
toDays(long d)103         public long toDays(long d)    { return d/(C6/C1); }
convert(long d, TimeUnit u)104         public long convert(long d, TimeUnit u) { return u.toMicros(d); }
excessNanos(long d, long m)105         int excessNanos(long d, long m) { return (int)((d*C1) - (m*C2)); }
106     },
107 
108     /**
109      * Time unit representing one thousandth of a second.
110      */
111     MILLISECONDS {
toNanos(long d)112         public long toNanos(long d)   { return x(d, C2/C0, MAX/(C2/C0)); }
toMicros(long d)113         public long toMicros(long d)  { return x(d, C2/C1, MAX/(C2/C1)); }
toMillis(long d)114         public long toMillis(long d)  { return d; }
toSeconds(long d)115         public long toSeconds(long d) { return d/(C3/C2); }
toMinutes(long d)116         public long toMinutes(long d) { return d/(C4/C2); }
toHours(long d)117         public long toHours(long d)   { return d/(C5/C2); }
toDays(long d)118         public long toDays(long d)    { return d/(C6/C2); }
convert(long d, TimeUnit u)119         public long convert(long d, TimeUnit u) { return u.toMillis(d); }
excessNanos(long d, long m)120         int excessNanos(long d, long m) { return 0; }
121     },
122 
123     /**
124      * Time unit representing one second.
125      */
126     SECONDS {
toNanos(long d)127         public long toNanos(long d)   { return x(d, C3/C0, MAX/(C3/C0)); }
toMicros(long d)128         public long toMicros(long d)  { return x(d, C3/C1, MAX/(C3/C1)); }
toMillis(long d)129         public long toMillis(long d)  { return x(d, C3/C2, MAX/(C3/C2)); }
toSeconds(long d)130         public long toSeconds(long d) { return d; }
toMinutes(long d)131         public long toMinutes(long d) { return d/(C4/C3); }
toHours(long d)132         public long toHours(long d)   { return d/(C5/C3); }
toDays(long d)133         public long toDays(long d)    { return d/(C6/C3); }
convert(long d, TimeUnit u)134         public long convert(long d, TimeUnit u) { return u.toSeconds(d); }
excessNanos(long d, long m)135         int excessNanos(long d, long m) { return 0; }
136     },
137 
138     /**
139      * Time unit representing sixty seconds.
140      * @since 1.6
141      */
142     MINUTES {
toNanos(long d)143         public long toNanos(long d)   { return x(d, C4/C0, MAX/(C4/C0)); }
toMicros(long d)144         public long toMicros(long d)  { return x(d, C4/C1, MAX/(C4/C1)); }
toMillis(long d)145         public long toMillis(long d)  { return x(d, C4/C2, MAX/(C4/C2)); }
toSeconds(long d)146         public long toSeconds(long d) { return x(d, C4/C3, MAX/(C4/C3)); }
toMinutes(long d)147         public long toMinutes(long d) { return d; }
toHours(long d)148         public long toHours(long d)   { return d/(C5/C4); }
toDays(long d)149         public long toDays(long d)    { return d/(C6/C4); }
convert(long d, TimeUnit u)150         public long convert(long d, TimeUnit u) { return u.toMinutes(d); }
excessNanos(long d, long m)151         int excessNanos(long d, long m) { return 0; }
152     },
153 
154     /**
155      * Time unit representing sixty minutes.
156      * @since 1.6
157      */
158     HOURS {
toNanos(long d)159         public long toNanos(long d)   { return x(d, C5/C0, MAX/(C5/C0)); }
toMicros(long d)160         public long toMicros(long d)  { return x(d, C5/C1, MAX/(C5/C1)); }
toMillis(long d)161         public long toMillis(long d)  { return x(d, C5/C2, MAX/(C5/C2)); }
toSeconds(long d)162         public long toSeconds(long d) { return x(d, C5/C3, MAX/(C5/C3)); }
toMinutes(long d)163         public long toMinutes(long d) { return x(d, C5/C4, MAX/(C5/C4)); }
toHours(long d)164         public long toHours(long d)   { return d; }
toDays(long d)165         public long toDays(long d)    { return d/(C6/C5); }
convert(long d, TimeUnit u)166         public long convert(long d, TimeUnit u) { return u.toHours(d); }
excessNanos(long d, long m)167         int excessNanos(long d, long m) { return 0; }
168     },
169 
170     /**
171      * Time unit representing twenty four hours.
172      * @since 1.6
173      */
174     DAYS {
toNanos(long d)175         public long toNanos(long d)   { return x(d, C6/C0, MAX/(C6/C0)); }
toMicros(long d)176         public long toMicros(long d)  { return x(d, C6/C1, MAX/(C6/C1)); }
toMillis(long d)177         public long toMillis(long d)  { return x(d, C6/C2, MAX/(C6/C2)); }
toSeconds(long d)178         public long toSeconds(long d) { return x(d, C6/C3, MAX/(C6/C3)); }
toMinutes(long d)179         public long toMinutes(long d) { return x(d, C6/C4, MAX/(C6/C4)); }
toHours(long d)180         public long toHours(long d)   { return x(d, C6/C5, MAX/(C6/C5)); }
toDays(long d)181         public long toDays(long d)    { return d; }
convert(long d, TimeUnit u)182         public long convert(long d, TimeUnit u) { return u.toDays(d); }
excessNanos(long d, long m)183         int excessNanos(long d, long m) { return 0; }
184     };
185 
186     // Handy constants for conversion methods
187     static final long C0 = 1L;
188     static final long C1 = C0 * 1000L;
189     static final long C2 = C1 * 1000L;
190     static final long C3 = C2 * 1000L;
191     static final long C4 = C3 * 60L;
192     static final long C5 = C4 * 60L;
193     static final long C6 = C5 * 24L;
194 
195     static final long MAX = Long.MAX_VALUE;
196 
197     /**
198      * Scale d by m, checking for overflow.
199      * This has a short name to make above code more readable.
200      */
x(long d, long m, long over)201     static long x(long d, long m, long over) {
202         if (d > +over) return Long.MAX_VALUE;
203         if (d < -over) return Long.MIN_VALUE;
204         return d * m;
205     }
206 
207     // To maintain full signature compatibility with 1.5, and to improve the
208     // clarity of the generated javadoc (see 6287639: Abstract methods in
209     // enum classes should not be listed as abstract), method convert
210     // etc. are not declared abstract but otherwise act as abstract methods.
211 
212     /**
213      * Converts the given time duration in the given unit to this unit.
214      * Conversions from finer to coarser granularities truncate, so
215      * lose precision. For example, converting {@code 999} milliseconds
216      * to seconds results in {@code 0}. Conversions from coarser to
217      * finer granularities with arguments that would numerically
218      * overflow saturate to {@code Long.MIN_VALUE} if negative or
219      * {@code Long.MAX_VALUE} if positive.
220      *
221      * <p>For example, to convert 10 minutes to milliseconds, use:
222      * {@code TimeUnit.MILLISECONDS.convert(10L, TimeUnit.MINUTES)}
223      *
224      * @param sourceDuration the time duration in the given {@code sourceUnit}
225      * @param sourceUnit the unit of the {@code sourceDuration} argument
226      * @return the converted duration in this unit,
227      * or {@code Long.MIN_VALUE} if conversion would negatively
228      * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
229      */
convert(long sourceDuration, TimeUnit sourceUnit)230     public long convert(long sourceDuration, TimeUnit sourceUnit) {
231         throw new AbstractMethodError();
232     }
233 
234     /**
235      * Equivalent to
236      * {@link #convert(long, TimeUnit) NANOSECONDS.convert(duration, this)}.
237      * @param duration the duration
238      * @return the converted duration,
239      * or {@code Long.MIN_VALUE} if conversion would negatively
240      * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
241      */
toNanos(long duration)242     public long toNanos(long duration) {
243         throw new AbstractMethodError();
244     }
245 
246     /**
247      * Equivalent to
248      * {@link #convert(long, TimeUnit) MICROSECONDS.convert(duration, this)}.
249      * @param duration the duration
250      * @return the converted duration,
251      * or {@code Long.MIN_VALUE} if conversion would negatively
252      * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
253      */
toMicros(long duration)254     public long toMicros(long duration) {
255         throw new AbstractMethodError();
256     }
257 
258     /**
259      * Equivalent to
260      * {@link #convert(long, TimeUnit) MILLISECONDS.convert(duration, this)}.
261      * @param duration the duration
262      * @return the converted duration,
263      * or {@code Long.MIN_VALUE} if conversion would negatively
264      * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
265      */
toMillis(long duration)266     public long toMillis(long duration) {
267         throw new AbstractMethodError();
268     }
269 
270     /**
271      * Equivalent to
272      * {@link #convert(long, TimeUnit) SECONDS.convert(duration, this)}.
273      * @param duration the duration
274      * @return the converted duration,
275      * or {@code Long.MIN_VALUE} if conversion would negatively
276      * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
277      */
toSeconds(long duration)278     public long toSeconds(long duration) {
279         throw new AbstractMethodError();
280     }
281 
282     /**
283      * Equivalent to
284      * {@link #convert(long, TimeUnit) MINUTES.convert(duration, this)}.
285      * @param duration the duration
286      * @return the converted duration,
287      * or {@code Long.MIN_VALUE} if conversion would negatively
288      * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
289      * @since 1.6
290      */
toMinutes(long duration)291     public long toMinutes(long duration) {
292         throw new AbstractMethodError();
293     }
294 
295     /**
296      * Equivalent to
297      * {@link #convert(long, TimeUnit) HOURS.convert(duration, this)}.
298      * @param duration the duration
299      * @return the converted duration,
300      * or {@code Long.MIN_VALUE} if conversion would negatively
301      * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
302      * @since 1.6
303      */
toHours(long duration)304     public long toHours(long duration) {
305         throw new AbstractMethodError();
306     }
307 
308     /**
309      * Equivalent to
310      * {@link #convert(long, TimeUnit) DAYS.convert(duration, this)}.
311      * @param duration the duration
312      * @return the converted duration
313      * @since 1.6
314      */
toDays(long duration)315     public long toDays(long duration) {
316         throw new AbstractMethodError();
317     }
318 
319     /**
320      * Utility to compute the excess-nanosecond argument to wait,
321      * sleep, join.
322      * @param d the duration
323      * @param m the number of milliseconds
324      * @return the number of nanoseconds
325      */
excessNanos(long d, long m)326     abstract int excessNanos(long d, long m);
327 
328     /**
329      * Performs a timed {@link Object#wait(long, int) Object.wait}
330      * using this time unit.
331      * This is a convenience method that converts timeout arguments
332      * into the form required by the {@code Object.wait} method.
333      *
334      * <p>For example, you could implement a blocking {@code poll}
335      * method (see {@link BlockingQueue#poll BlockingQueue.poll})
336      * using:
337      *
338      * <pre> {@code
339      * public synchronized Object poll(long timeout, TimeUnit unit)
340      *     throws InterruptedException {
341      *   while (empty) {
342      *     unit.timedWait(this, timeout);
343      *     ...
344      *   }
345      * }}</pre>
346      *
347      * @param obj the object to wait on
348      * @param timeout the maximum time to wait. If less than
349      * or equal to zero, do not wait at all.
350      * @throws InterruptedException if interrupted while waiting
351      */
timedWait(Object obj, long timeout)352     public void timedWait(Object obj, long timeout)
353             throws InterruptedException {
354         if (timeout > 0) {
355             long ms = toMillis(timeout);
356             int ns = excessNanos(timeout, ms);
357             obj.wait(ms, ns);
358         }
359     }
360 
361     /**
362      * Performs a timed {@link Thread#join(long, int) Thread.join}
363      * using this time unit.
364      * This is a convenience method that converts time arguments into the
365      * form required by the {@code Thread.join} method.
366      *
367      * @param thread the thread to wait for
368      * @param timeout the maximum time to wait. If less than
369      * or equal to zero, do not wait at all.
370      * @throws InterruptedException if interrupted while waiting
371      */
timedJoin(Thread thread, long timeout)372     public void timedJoin(Thread thread, long timeout)
373             throws InterruptedException {
374         if (timeout > 0) {
375             long ms = toMillis(timeout);
376             int ns = excessNanos(timeout, ms);
377             thread.join(ms, ns);
378         }
379     }
380 
381     /**
382      * Performs a {@link Thread#sleep(long, int) Thread.sleep} using
383      * this time unit.
384      * This is a convenience method that converts time arguments into the
385      * form required by the {@code Thread.sleep} method.
386      *
387      * @param timeout the minimum time to sleep. If less than
388      * or equal to zero, do not sleep at all.
389      * @throws InterruptedException if interrupted while sleeping
390      */
sleep(long timeout)391     public void sleep(long timeout) throws InterruptedException {
392         if (timeout > 0) {
393             long ms = toMillis(timeout);
394             int ns = excessNanos(timeout, ms);
395             Thread.sleep(ms, ns);
396         }
397     }
398 }
399