9 |
|
import junit.framework.*; |
10 |
|
import java.util.*; |
11 |
|
import java.util.concurrent.*; |
12 |
+ |
import java.math.BigInteger; |
13 |
|
|
14 |
|
public class ExecutorsTest extends TestCase{ |
15 |
|
|
311 |
|
} |
312 |
|
} |
313 |
|
|
314 |
+ |
/** |
315 |
+ |
* Check that timeouts from execute will time out if they compute |
316 |
+ |
* too long. |
317 |
+ |
*/ |
318 |
+ |
|
319 |
+ |
public void testTimedCallable() { |
320 |
+ |
int N = 10000; |
321 |
+ |
ExecutorService executor = Executors.newSingleThreadExecutor(); |
322 |
+ |
List<Callable<BigInteger>> tasks = new ArrayList<Callable<BigInteger>>(N); |
323 |
+ |
try { |
324 |
+ |
long startTime = System.currentTimeMillis(); |
325 |
+ |
|
326 |
+ |
long i = 0; |
327 |
+ |
while (tasks.size() < N) { |
328 |
+ |
tasks.add(new TimedCallable<BigInteger>(executor, new Fib(i), 1)); |
329 |
+ |
i += 10; |
330 |
+ |
} |
331 |
+ |
|
332 |
+ |
int iters = 0; |
333 |
+ |
BigInteger sum = BigInteger.ZERO; |
334 |
+ |
for (Iterator<Callable<BigInteger>> it = tasks.iterator(); it.hasNext();) { |
335 |
+ |
try { |
336 |
+ |
++iters; |
337 |
+ |
sum = sum.add(it.next().call()); |
338 |
+ |
} |
339 |
+ |
catch (TimeoutException success) { |
340 |
+ |
assertTrue(iters > 0); |
341 |
+ |
return; |
342 |
+ |
} |
343 |
+ |
catch (Exception e) { |
344 |
+ |
fail("unexpected exception: " + e); |
345 |
+ |
} |
346 |
+ |
} |
347 |
+ |
// if by chance we didn't ever time out, total time must be small |
348 |
+ |
long elapsed = System.currentTimeMillis() - startTime; |
349 |
+ |
assertTrue(elapsed < N); |
350 |
+ |
} |
351 |
+ |
finally { |
352 |
+ |
executor.shutdownNow(); |
353 |
+ |
} |
354 |
+ |
} |
355 |
+ |
|
356 |
+ |
|
357 |
+ |
static class TimedCallable<T> implements Callable<T> { |
358 |
+ |
private final Executor exec; |
359 |
+ |
private final Callable<T> func; |
360 |
+ |
private final long msecs; |
361 |
+ |
|
362 |
+ |
TimedCallable(Executor exec, Callable<T> func, long msecs) { |
363 |
+ |
this.exec = exec; |
364 |
+ |
this.func = func; |
365 |
+ |
this.msecs = msecs; |
366 |
+ |
} |
367 |
+ |
|
368 |
+ |
public T call() throws Exception { |
369 |
+ |
Future<T> ftask = Executors.execute(exec, func); |
370 |
+ |
try { |
371 |
+ |
return ftask.get(msecs, TimeUnit.MILLISECONDS); |
372 |
+ |
} finally { |
373 |
+ |
ftask.cancel(true); |
374 |
+ |
} |
375 |
+ |
} |
376 |
+ |
} |
377 |
+ |
|
378 |
+ |
|
379 |
+ |
private static class Fib implements Callable<BigInteger> { |
380 |
+ |
private final BigInteger n; |
381 |
+ |
Fib(long n) { |
382 |
+ |
if (n < 0) throw new IllegalArgumentException("need non-negative arg, but got " + n); |
383 |
+ |
this.n = BigInteger.valueOf(n); |
384 |
+ |
} |
385 |
+ |
public BigInteger call() { |
386 |
+ |
BigInteger f1 = BigInteger.ONE; |
387 |
+ |
BigInteger f2 = f1; |
388 |
+ |
for (BigInteger i = BigInteger.ZERO; i.compareTo(n) < 0; i = i.add(BigInteger.ONE)) { |
389 |
+ |
BigInteger t = f1.add(f2); |
390 |
+ |
f1 = f2; |
391 |
+ |
f2 = t; |
392 |
+ |
} |
393 |
+ |
return f1; |
394 |
+ |
} |
395 |
+ |
}; |
396 |
+ |
|
397 |
+ |
|
398 |
|
|
399 |
|
} |