ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/ExecutorsTest.java
Revision: 1.4
Committed: Sat Sep 20 18:20:07 2003 UTC (20 years, 7 months ago) by dl
Branch: MAIN
Changes since 1.3: +137 -134 lines
Log Message:
Documentation scaffolding

File Contents

# User Rev Content
1 dl 1.1 /*
2     * Written by members of JCP JSR-166 Expert Group and released to the
3     * public domain. Use, modify, and redistribute this code in any way
4     * without acknowledgement. Other contributors include Andrew Wright,
5     * Jeffrey Hayes, Pat Fischer, Mike Judd.
6     */
7    
8    
9     import junit.framework.*;
10     import java.util.*;
11     import java.util.concurrent.*;
12 dl 1.2 import java.math.BigInteger;
13 dl 1.1
14 dl 1.3 public class ExecutorsTest extends JSR166TestCase{
15 dl 1.4
16 dl 1.1 public static void main(String[] args) {
17     junit.textui.TestRunner.run (suite());
18     }
19     public static Test suite() {
20     return new TestSuite(ExecutorsTest.class);
21     }
22    
23 dl 1.4 private static final String TEST_STRING = "a test string";
24    
25     private static class MyTask implements Runnable {
26     public void run() { completed = true; }
27     public boolean isCompleted() { return completed; }
28     public void reset() { completed = false; }
29     private boolean completed = false;
30     }
31    
32     private static class StringTask implements Callable<String> {
33     public String call() { return TEST_STRING; }
34     }
35    
36     static class DirectExecutor implements Executor {
37     public void execute(Runnable r) {
38     r.run();
39     }
40     }
41    
42     static class TimedCallable<T> implements Callable<T> {
43     private final Executor exec;
44     private final Callable<T> func;
45     private final long msecs;
46    
47     TimedCallable(Executor exec, Callable<T> func, long msecs) {
48     this.exec = exec;
49     this.func = func;
50     this.msecs = msecs;
51     }
52    
53     public T call() throws Exception {
54     Future<T> ftask = Executors.execute(exec, func);
55     try {
56     return ftask.get(msecs, TimeUnit.MILLISECONDS);
57     } finally {
58     ftask.cancel(true);
59     }
60     }
61     }
62    
63    
64     private static class Fib implements Callable<BigInteger> {
65     private final BigInteger n;
66     Fib(long n) {
67     if (n < 0) throw new IllegalArgumentException("need non-negative arg, but got " + n);
68     this.n = BigInteger.valueOf(n);
69     }
70     public BigInteger call() {
71     BigInteger f1 = BigInteger.ONE;
72     BigInteger f2 = f1;
73     for (BigInteger i = BigInteger.ZERO; i.compareTo(n) < 0; i = i.add(BigInteger.ONE)) {
74     BigInteger t = f1.add(f2);
75     f1 = f2;
76     f2 = t;
77     }
78     return f1;
79     }
80     };
81    
82    
83    
84 dl 1.1 /**
85 dl 1.3 * execute(Executor, Runnable) will throw
86 dl 1.1 * RejectedExecutionException Attempting to execute a runnable on
87     * a full ThreadPool will cause such an exception here, up to 5
88     * runnables are attempted on a pool capable on handling one
89     * until it throws an exception
90     */
91 dl 1.4 public void testExecute1() {
92 dl 1.3 ThreadPoolExecutor p = new ThreadPoolExecutor(1,1, SHORT_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1));
93 dl 1.4 try {
94 dl 1.1
95     for(int i = 0; i < 5; ++i){
96 dl 1.3 Executors.execute(p, new MediumRunnable(), Boolean.TRUE);
97 dl 1.1 }
98 dl 1.4 shouldThrow();
99 dl 1.1 } catch(RejectedExecutionException success){}
100 dl 1.3 joinPool(p);
101 dl 1.1 }
102    
103     /**
104 dl 1.3 * execute(Executor, Callable) will throw
105 dl 1.1 * RejectedExecutionException Attempting to execute a callable on
106     * a full ThreadPool will cause such an exception here, up to 5
107     * runnables are attempted on a pool capable on handling one
108     * until it throws an exception
109     */
110 dl 1.4 public void testExecute2() {
111 dl 1.3 ThreadPoolExecutor p = new ThreadPoolExecutor(1,1, SHORT_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1));
112 dl 1.4 try {
113 dl 1.1 for(int i = 0; i < 5; ++i) {
114 dl 1.3 Executors.execute(p, new SmallCallable());
115 dl 1.1 }
116 dl 1.4 shouldThrow();
117     } catch(RejectedExecutionException e){}
118 dl 1.3 joinPool(p);
119 dl 1.1 }
120    
121    
122     /**
123 dl 1.3 * invoke(Executor, Runnable) throws InterruptedException
124 dl 1.1 * A single use of invoke starts that will wait long enough
125     * for the invoking thread to be interrupted
126     */
127 dl 1.4 public void testInvoke2() {
128 dl 1.3 final ThreadPoolExecutor p = new ThreadPoolExecutor(1,1,SHORT_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
129 dl 1.1 Thread t = new Thread(new Runnable() {
130 dl 1.4 public void run() {
131     try {
132     Executors.invoke(p,new Runnable() {
133     public void run() {
134     try {
135 dl 1.1 Thread.sleep(MEDIUM_DELAY_MS);
136 dl 1.4 shouldThrow();
137     } catch(InterruptedException e){
138 dl 1.1 }
139     }
140     });
141     } catch(InterruptedException success){
142     } catch(Exception e) {
143 dl 1.4 unexpectedException();
144 dl 1.1 }
145    
146     }
147     });
148 dl 1.4 try {
149 dl 1.1 t.start();
150     Thread.sleep(SHORT_DELAY_MS);
151     t.interrupt();
152 dl 1.4 } catch(Exception e){
153     unexpectedException();
154 dl 1.1 }
155 dl 1.3 joinPool(p);
156 dl 1.1 }
157    
158     /**
159 dl 1.3 * invoke(Executor, Runnable) will throw
160 dl 1.1 * ExecutionException An ExecutionException occurs when the
161     * underlying Runnable throws an exception, here the
162     * DivideByZeroException will cause an ExecutionException
163     */
164 dl 1.4 public void testInvoke3() {
165 dl 1.3 ThreadPoolExecutor p = new ThreadPoolExecutor(1,1,SHORT_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
166 dl 1.4 try {
167     Runnable r = new Runnable() {
168     public void run() {
169 dl 1.1 int i = 5/0;
170     }
171     };
172    
173     for(int i =0; i < 5; i++){
174     Executors.invoke(p,r);
175     }
176    
177 dl 1.4 shouldThrow();
178 dl 1.1 } catch(ExecutionException success){
179     } catch(Exception e){
180 dl 1.4 unexpectedException();
181 dl 1.1 }
182 dl 1.3 joinPool(p);
183 dl 1.1 }
184    
185    
186    
187     /**
188 dl 1.3 * invoke(Executor, Callable) throws
189 dl 1.1 * InterruptedException A single use of invoke starts that will
190     * wait long enough for the invoking thread to be interrupted
191     */
192 dl 1.4 public void testInvoke5() {
193 dl 1.3 final ThreadPoolExecutor p = new ThreadPoolExecutor(1,1,SHORT_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
194 dl 1.1
195 dl 1.4 final Callable c = new Callable() {
196     public Object call() {
197     try {
198 dl 1.3 Executors.invoke(p, new SmallCallable());
199 dl 1.4 shouldThrow();
200     } catch(InterruptedException e){}
201 dl 1.1 catch(RejectedExecutionException e2){}
202     catch(ExecutionException e3){}
203     return Boolean.TRUE;
204     }
205     };
206    
207    
208    
209 dl 1.4 Thread t = new Thread(new Runnable() {
210     public void run() {
211     try {
212 dl 1.1 c.call();
213 dl 1.4 } catch(Exception e){}
214 dl 1.1 }
215     });
216 dl 1.4 try {
217 dl 1.1 t.start();
218     Thread.sleep(SHORT_DELAY_MS);
219     t.interrupt();
220     t.join();
221 dl 1.4 } catch(InterruptedException e){
222     unexpectedException();
223 dl 1.1 }
224    
225 dl 1.3 joinPool(p);
226 dl 1.1 }
227    
228     /**
229 dl 1.3 * invoke(Executor, Callable) will throw ExecutionException
230 dl 1.1 * An ExecutionException occurs when the underlying Runnable throws
231     * an exception, here the DivideByZeroException will cause an ExecutionException
232     */
233 dl 1.4 public void testInvoke6() {
234 dl 1.3 ThreadPoolExecutor p = new ThreadPoolExecutor(1,1,SHORT_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
235 dl 1.1
236 dl 1.4 try {
237     Callable c = new Callable() {
238     public Object call() {
239 dl 1.1 int i = 5/0;
240     return Boolean.TRUE;
241     }
242     };
243    
244     for(int i =0; i < 5; i++){
245     Executors.invoke(p,c);
246     }
247    
248 dl 1.4 shouldThrow();
249     } catch(RejectedExecutionException e){}
250 dl 1.1 catch(InterruptedException e2){}
251     catch(ExecutionException e3){}
252 dl 1.3 joinPool(p);
253 dl 1.1 }
254    
255 dl 1.4 /**
256     *
257     */
258 dl 1.1 public void testExecuteRunnable () {
259     try {
260     Executor e = new DirectExecutor();
261 dl 1.4 MyTask task = new MyTask();
262     assertFalse(task.isCompleted());
263 dl 1.1 Future<String> future = Executors.execute(e, task, TEST_STRING);
264     String result = future.get();
265 dl 1.4 assertTrue(task.isCompleted());
266     assertSame(TEST_STRING, result);
267 dl 1.1 }
268     catch (ExecutionException ex) {
269 dl 1.4 unexpectedException();
270 dl 1.1 }
271     catch (InterruptedException ex) {
272 dl 1.4 unexpectedException();
273 dl 1.1 }
274     }
275    
276 dl 1.4 /**
277     *
278     */
279 dl 1.1 public void testInvokeRunnable () {
280     try {
281     Executor e = new DirectExecutor();
282 dl 1.4 MyTask task = new MyTask();
283     assertFalse(task.isCompleted());
284 dl 1.1 Executors.invoke(e, task);
285 dl 1.4 assertTrue(task.isCompleted());
286 dl 1.1 }
287     catch (ExecutionException ex) {
288 dl 1.4 unexpectedException();
289 dl 1.1 }
290     catch (InterruptedException ex) {
291 dl 1.4 unexpectedException();
292 dl 1.1 }
293     }
294    
295 dl 1.4 /**
296     *
297     */
298 dl 1.1 public void testExecuteCallable () {
299     try {
300     Executor e = new DirectExecutor();
301     Future<String> future = Executors.execute(e, new StringTask());
302     String result = future.get();
303 dl 1.4 assertSame(TEST_STRING, result);
304 dl 1.1 }
305     catch (ExecutionException ex) {
306 dl 1.4 unexpectedException();
307 dl 1.1 }
308     catch (InterruptedException ex) {
309 dl 1.4 unexpectedException();
310 dl 1.1 }
311     }
312    
313 dl 1.4 /**
314     *
315     */
316 dl 1.1 public void testInvokeCallable () {
317     try {
318     Executor e = new DirectExecutor();
319     String result = Executors.invoke(e, new StringTask());
320    
321 dl 1.4 assertSame(TEST_STRING, result);
322 dl 1.1 }
323     catch (ExecutionException ex) {
324 dl 1.4 unexpectedException();
325 dl 1.1 }
326     catch (InterruptedException ex) {
327 dl 1.4 unexpectedException();
328 dl 1.1 }
329     }
330 dl 1.2
331     /**
332 dl 1.4 * timeouts from execute will time out if they compute too long.
333 dl 1.2 */
334     public void testTimedCallable() {
335     int N = 10000;
336     ExecutorService executor = Executors.newSingleThreadExecutor();
337     List<Callable<BigInteger>> tasks = new ArrayList<Callable<BigInteger>>(N);
338     try {
339     long startTime = System.currentTimeMillis();
340    
341     long i = 0;
342     while (tasks.size() < N) {
343     tasks.add(new TimedCallable<BigInteger>(executor, new Fib(i), 1));
344     i += 10;
345     }
346    
347     int iters = 0;
348     BigInteger sum = BigInteger.ZERO;
349     for (Iterator<Callable<BigInteger>> it = tasks.iterator(); it.hasNext();) {
350     try {
351     ++iters;
352     sum = sum.add(it.next().call());
353     }
354     catch (TimeoutException success) {
355     assertTrue(iters > 0);
356     return;
357     }
358     catch (Exception e) {
359 dl 1.4 unexpectedException();
360 dl 1.2 }
361     }
362     // if by chance we didn't ever time out, total time must be small
363     long elapsed = System.currentTimeMillis() - startTime;
364     assertTrue(elapsed < N);
365     }
366     finally {
367 dl 1.3 joinPool(executor);
368 dl 1.2 }
369     }
370    
371    
372 dl 1.1
373    
374     }