ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/TimeUnit.java
Revision: 1.14
Committed: Fri Sep 12 20:17:50 2003 UTC (20 years, 9 months ago) by dl
Branch: MAIN
Changes since 1.13: +66 -78 lines
Log Message:
Use readResolve to deserialize

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