ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/TimeUnit.java
Revision: 1.18
Committed: Sat Dec 27 19:26:26 2003 UTC (20 years, 5 months ago) by dl
Branch: MAIN
Changes since 1.17: +2 -2 lines
Log Message:
Headers reference Creative Commons

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/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.
13 * <tt>TimeUnit</tt> is a &quot;featherweight&quot; class.
14 * It does not maintain time information, but only helps organize and
15 * use time representations that may be maintained separately across
16 * various contexts.
17 *
18 * <p>This class cannot be directly instantiated. Use the {@link
19 * #SECONDS}, {@link #MILLISECONDS}, {@link #MICROSECONDS}, and {@link
20 * #NANOSECONDS} static instances that provide predefined units of
21 * precision. If you use these frequently, consider statically
22 * importing this class.
23 *
24 * <p>A <tt>TimeUnit</tt> is mainly used to inform blocking methods which
25 * can timeout, how the timeout parameter should be interpreted. For example,
26 * the following code will timeout in 50 milliseconds if the {@link java.util.concurrent.locks.Lock lock}
27 * is not available:
28 * <pre> Lock lock = ...;
29 * if ( lock.tryLock(50L, TimeUnit.MILLISECONDS) ) ...
30 * </pre>
31 * while this code will timeout in 50 seconds:
32 * <pre>
33 * Lock lock = ...;
34 * if ( lock.tryLock(50L, TimeUnit.SECONDS) ) ...
35 * </pre>
36 *
37 * Note however, that there is no guarantee that a particular timeout
38 * implementation will be able to notice the passage of time at the
39 * same granularity as the given <tt>TimeUnit</tt>.
40 *
41 * @since 1.5
42 * @author Doug Lea
43 */
44 public final class TimeUnit implements java.io.Serializable {
45 /* ordered indices for each time unit */
46 private static final int NS = 0;
47 private static final int US = 1;
48 private static final int MS = 2;
49 private static final int S = 3;
50
51 /** quick lookup table for conversion factors */
52 private static final int[] multipliers = { 1,
53 1000,
54 1000*1000,
55 1000*1000*1000 };
56
57 /** lookup table to check saturation */
58 private static final long[] overflows = {
59 // Note that because we are dividing these down anyway,
60 // we don't have to deal with asymmetry of MIN/MAX values.
61 0, // unused
62 Long.MAX_VALUE / 1000,
63 Long.MAX_VALUE / (1000 * 1000),
64 Long.MAX_VALUE / (1000 * 1000 * 1000) };
65
66 /** the index of this unit */
67 private int index;
68 /** Common name for unit */
69 private final String unitName;
70
71 /** private constructor */
72 TimeUnit(int index, String name) {
73 this.index = index;
74 this.unitName = name;
75 }
76
77 /** Unit for one-second granularities. */
78 public static final TimeUnit SECONDS = new TimeUnit(S, "seconds");
79 /** Unit for one-millisecond granularities. */
80 public static final TimeUnit MILLISECONDS = new TimeUnit(MS, "milliseconds");
81 /** Unit for one-microsecond granularities. */
82 public static final TimeUnit MICROSECONDS = new TimeUnit(US, "microseconds");
83 /** Unit for one-nanosecond granularities. */
84 public static final TimeUnit NANOSECONDS = new TimeUnit(NS, "nanoseconds");
85
86 /**
87 * Utility method to compute the excess-nanosecond argument to
88 * wait, sleep, join.
89 */
90 private int excessNanos(long time, long ms) {
91 if (index == NS)
92 return (int) (time - (ms * multipliers[MS-NS]));
93 else if (index == US)
94 return (int) ((time * multipliers[US-NS]) - (ms * multipliers[MS-NS]));
95 else
96 return 0;
97 }
98
99 /**
100 * Perform conversion based on given delta representing the
101 * difference between units
102 * @param delta the difference in index values of source and target units
103 * @param duration the duration
104 * @return converted duration or saturated value
105 */
106 private static long doConvert(int delta, long duration) {
107 if (delta == 0)
108 return duration;
109 if (delta < 0)
110 return duration / multipliers[-delta];
111 if (duration > overflows[delta])
112 return Long.MAX_VALUE;
113 if (duration < -overflows[delta])
114 return Long.MIN_VALUE;
115 return duration * multipliers[delta];
116 }
117
118 /**
119 * Convert the given time duration in the given unit to this
120 * unit. Conversions from finer to coarser granularities
121 * truncate, so lose precision. For example converting
122 * <tt>999</tt> milliseconds to seconds results in
123 * <tt>0</tt>. Conversions from coarser to finer granularities
124 * with arguments that would numerically overflow saturate to
125 * <tt>Long.MIN_VALUE</tt> if negative or <tt>Long.MAX_VALUE</tt>
126 * if positive.
127 *
128 * @param duration the time duration in the given <tt>unit</tt>
129 * @param unit the unit of the <tt>duration</tt> argument
130 * @return the converted duration in this unit,
131 * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
132 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
133 */
134 public long convert(long duration, TimeUnit unit) {
135 return doConvert(unit.index - index, duration);
136 }
137
138 /**
139 * Equivalent to <tt>NANOSECONDS.convert(duration, this)</tt>.
140 * @param duration the duration
141 * @return the converted duration,
142 * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
143 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
144 * @see #convert
145 */
146 public long toNanos(long duration) {
147 return doConvert(index, duration);
148 }
149
150 /**
151 * Equivalent to <tt>MICROSECONDS.convert(duration, this)</tt>.
152 * @param duration the duration
153 * @return the converted duration,
154 * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
155 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
156 * @see #convert
157 */
158 public long toMicros(long duration) {
159 return doConvert(index - US, duration);
160 }
161
162 /**
163 * Equivalent to <tt>MILLISECONDS.convert(duration, this)</tt>.
164 * @param duration the duration
165 * @return the converted duration,
166 * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
167 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
168 * @see #convert
169 */
170 public long toMillis(long duration) {
171 return doConvert(index - MS, duration);
172 }
173
174 /**
175 * Equivalent to <tt>SECONDS.convert(duration, this)</tt>.
176 * @param duration the duration
177 * @return the converted duration.
178 * @see #convert
179 */
180 public long toSeconds(long duration) {
181 return doConvert(index - S, duration);
182 }
183
184 /**
185 * Perform a timed <tt>Object.wait</tt> using this time unit.
186 * This is a convenience method that converts timeout arguments into the
187 * form required by the <tt>Object.wait</tt> method.
188 * <p>For example, you could implement a blocking <tt>poll</tt> method (see
189 * {@link BlockingQueue#poll BlockingQueue.poll} using:
190 * <pre> public synchronized Object poll(long timeout, TimeUnit unit) throws InterruptedException {
191 * while (empty) {
192 * unit.timedWait(this, timeout);
193 * ...
194 * }
195 * }</pre>
196 * @param obj the object to wait on
197 * @param timeout the maximum time to wait.
198 * @throws InterruptedException if interrupted while waiting.
199 * @see Object#wait(long, int)
200 */
201 public void timedWait(Object obj, long timeout)
202 throws InterruptedException {
203 if (timeout > 0) {
204 long ms = toMillis(timeout);
205 int ns = excessNanos(timeout, ms);
206 obj.wait(ms, ns);
207 }
208 }
209
210 /**
211 * Perform a timed <tt>Thread.join</tt> using this time unit.
212 * This is a convenience method that converts time arguments into the
213 * form required by the <tt>Thread.join</tt> method.
214 * @param thread the thread to wait for
215 * @param timeout the maximum time to wait
216 * @throws InterruptedException if interrupted while waiting.
217 * @see Thread#join(long, int)
218 */
219 public void timedJoin(Thread thread, long timeout)
220 throws InterruptedException {
221 if (timeout > 0) {
222 long ms = toMillis(timeout);
223 int ns = excessNanos(timeout, ms);
224 thread.join(ms, ns);
225 }
226 }
227
228 /**
229 * Perform a <tt>Thread.sleep</tt> using this unit.
230 * This is a convenience method that converts time arguments into the
231 * form required by the <tt>Thread.sleep</tt> method.
232 * @param timeout the minimum time to sleep
233 * @throws InterruptedException if interrupted while sleeping.
234 * @see Thread#sleep
235 */
236 public void sleep(long timeout) throws InterruptedException {
237 if (timeout > 0) {
238 long ms = toMillis(timeout);
239 int ns = excessNanos(timeout, ms);
240 Thread.sleep(ms, ns);
241 }
242 }
243
244 /**
245 * Return the common name for this unit.
246 */
247 public String toString() {
248 return unitName;
249 }
250
251 /**
252 * Resolves instances being deserialized to a single instance per
253 * unit.
254 */
255 private Object readResolve() {
256 switch(index) {
257 case NS: return NANOSECONDS;
258 case US: return MICROSECONDS;
259 case MS: return MILLISECONDS;
260 case S: return SECONDS;
261 default: assert(false); return null;
262 }
263 }
264 }