ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/TimeUnit.java
Revision: 1.13
Committed: Fri Sep 12 15:40:10 2003 UTC (20 years, 8 months ago) by dl
Branch: MAIN
Changes since 1.12: +85 -23 lines
Log Message:
Adapt AbstractQueue changes; Conditionalize CancellableTask.reset; new TimeUnit methods

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. Use, modify, and
4 * redistribute this code in any way without acknowledgement.
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 * Note however, that there is no guarantee that a particular lock, in this
37 * case, will be able to notice the passage of time at the same granularity
38 * as the given <tt>TimeUnit</tt>.
39 *
40 * @since 1.5
41 * @author Doug Lea
42 */
43 public final class TimeUnit implements java.io.Serializable {
44
45 /**
46 * Perform the conversion based on given index representing the
47 * difference between units
48 * @param delta the difference in index values of source and target units
49 * @param duration the duration
50 * @return converted duration or saturated value
51 */
52 private static long doConvert(int delta, long duration) {
53 if (delta == 0)
54 return duration;
55 if (delta < 0)
56 return duration / multipliers[-delta];
57 if (duration > overflows[delta])
58 return Long.MAX_VALUE;
59 if (duration < -overflows[delta])
60 return Long.MIN_VALUE;
61 return duration * multipliers[delta];
62 }
63
64 /**
65 * Convert the given time duration in the given unit to the
66 * current unit. Conversions from finer to coarser granulaties
67 * truncate, so lose precision. For example converting
68 * <tt>999</tt> milliseconds to seconds results in
69 * <tt>0</tt>. Conversions from coarser to finer granularities
70 * with arguments that would numerically overflow saturate to
71 * <tt>Long.MIN_VALUE</tt> if negative or <tt>Long.MAX_VALUE</tt>
72 * if positive.
73 *
74 * @param duration the time duration in the given <tt>unit</tt>
75 * @param unit the unit of the <tt>duration</tt> argument
76 * @return the converted duration in the current unit,
77 * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
78 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
79 */
80 public long convert(long duration, TimeUnit unit) {
81 return doConvert(unit.index - index, duration);
82 }
83
84 /**
85 * Equivalent to <tt>NANOSECONDS.convert(duration, this)</tt>.
86 * @param duration the duration
87 * @return the converted duration,
88 * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
89 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
90 * @see #convert
91 */
92 public long toNanos(long duration) {
93 return doConvert(index, duration);
94 }
95
96 /**
97 * Equivalent to <tt>MICROSECONDS.convert(duration, this)</tt>.
98 * @param duration the duration
99 * @return the converted duration,
100 * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
101 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
102 * @see #convert
103 */
104 public long toMicros(long duration) {
105 return doConvert(index - US, duration);
106 }
107
108 /**
109 * Equivalent to <tt>MILLISECONDS.convert(duration, this)</tt>.
110 * @param duration the duration
111 * @return the converted duration,
112 * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
113 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
114 * @see #convert
115 */
116 public long toMillis(long duration) {
117 return doConvert(index - MS, duration);
118 }
119
120 /**
121 * Equivalent to <tt>SECONDS.convert(duration, this)</tt>.
122 * @param duration the duration
123 * @return the converted duration.
124 * @see #convert
125 */
126 public long toSeconds(long duration) {
127 return doConvert(index - S, duration);
128 }
129
130 /**
131 * Perform a timed <tt>Object.wait</tt> using the current time unit.
132 * This is a convenience method that converts timeout arguments into the
133 * form required by the <tt>Object.wait</tt> method.
134 * <p>For example, you could implement a blocking <tt>poll</tt> method (see
135 * {@link BlockingQueue#poll BlockingQueue.poll} using:
136 * <pre> public synchronized Object poll(long timeout, TimeUnit unit) throws InterruptedException {
137 * while (empty) {
138 * unit.timedWait(this, timeout);
139 * ...
140 * }
141 * }</pre>
142 * @param obj the object to wait on
143 * @param timeout the maximum time to wait.
144 * @throws InterruptedException if interrupted while waiting.
145 * @see Object#wait(long, int)
146 */
147 public void timedWait(Object obj, long timeout)
148 throws InterruptedException {
149 if (timeout > 0) {
150 long ms = MILLISECONDS.convert(timeout, this);
151 int ns = excessNanos(timeout, ms);
152 obj.wait(ms, ns);
153 }
154 }
155
156 /**
157 * Perform a timed <tt>Thread.join</tt> using the current time unit.
158 * This is a convenience method that converts time arguments into the
159 * form required by the <tt>Thread.join</tt> method.
160 * @param thread the thread to wait for
161 * @param timeout the maximum time to wait
162 * @throws InterruptedException if interrupted while waiting.
163 * @see Thread#join(long, int)
164 */
165 public void timedJoin(Thread thread, long timeout)
166 throws InterruptedException {
167 if (timeout > 0) {
168 long ms = MILLISECONDS.convert(timeout, this);
169 int ns = excessNanos(timeout, ms);
170 thread.join(ms, ns);
171 }
172 }
173
174 /**
175 * Perform a <tt>Thread.sleep</tt> using the current time unit.
176 * This is a convenience method that converts time arguments into the
177 * form required by the <tt>Thread.sleep</tt> method.
178 * @param timeout the minimum time to sleep
179 * @throws InterruptedException if interrupted while sleeping.
180 * @see Thread#sleep
181 */
182 public void sleep(long timeout) throws InterruptedException {
183 if (timeout > 0) {
184 long ms = MILLISECONDS.convert(timeout, this);
185 int ns = excessNanos(timeout, ms);
186 Thread.sleep(ms, ns);
187 }
188 }
189
190 /**
191 * Return the common name for this unit.
192 */
193 public String toString() {
194 return unitName;
195 }
196
197
198 /**
199 * Returns true if the given object is a TimeUnit representing
200 * the same unit as this TimeUnit.
201 * @param x the object to compare
202 * @return true if equal
203 */
204 public boolean equals(Object x) {
205 if (!(x instanceof TimeUnit))
206 return false;
207 return ((TimeUnit)x).index == index;
208 }
209
210 /**
211 * Returns a hash code for this TimeUnit.
212 * @return the hash code
213 */
214 public int hashCode() {
215 return unitName.hashCode();
216 }
217
218 private final String unitName;
219
220 /* ordered indices for each time unit */
221 private static final int NS = 0;
222 private static final int US = 1;
223 private static final int MS = 2;
224 private static final int S = 3;
225
226 /** quick lookup table for conversion factors */
227 static final int[] multipliers = { 1,
228 1000,
229 1000*1000,
230 1000*1000*1000 };
231
232 /** lookup table to check saturation */
233 static final long[] overflows = {
234 // Note that because we are dividing these down anyway,
235 // we don't have to deal with asymmetry of MIN/MAX values.
236 0, // unused
237 Long.MAX_VALUE / 1000,
238 Long.MAX_VALUE / (1000 * 1000),
239 Long.MAX_VALUE / (1000 * 1000 * 1000) };
240
241 /** the index of this unit */
242 int index;
243
244 /** private constructor */
245 TimeUnit(int index, String name) {
246 this.index = index;
247 this.unitName = name;
248 }
249
250 /**
251 * Utility method to compute the excess-nanosecond argument to
252 * wait, sleep, join. The results may overflow, so public methods
253 * invoking this should document possible overflow unless
254 * overflow is known not to be possible for the given arguments.
255 */
256 private int excessNanos(long time, long ms) {
257 if (index == NS)
258 return (int) (time - (ms * multipliers[MS-NS]));
259 else if (index == US)
260 return (int) ((time * multipliers[US-NS]) - (ms * multipliers[MS-NS]));
261 else
262 return 0;
263 }
264
265 /** Unit for one-second granularities. */
266 public static final TimeUnit SECONDS = new TimeUnit(S, "seconds");
267
268 /** Unit for one-millisecond granularities. */
269 public static final TimeUnit MILLISECONDS = new TimeUnit(MS, "milliseconds");
270
271 /** Unit for one-microsecond granularities. */
272 public static final TimeUnit MICROSECONDS = new TimeUnit(US, "microseconds");
273
274 /** Unit for one-nanosecond granularities. */
275 public static final TimeUnit NANOSECONDS = new TimeUnit(NS, "nanoseconds");
276
277 }