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/publicdomain/zero/1.0/ 5 * Other contributors include Andrew Wright, Jeffrey Hayes, 6 * Pat Fisher, Mike Judd. 7 */ 8 9 package jsr166; 10 11 import static java.util.concurrent.TimeUnit.MILLISECONDS; 12 import static java.util.concurrent.TimeUnit.NANOSECONDS; 13 14 import java.util.ArrayList; 15 import java.util.List; 16 import java.util.concurrent.ArrayBlockingQueue; 17 import java.util.concurrent.BlockingQueue; 18 import java.util.concurrent.Callable; 19 import java.util.concurrent.CountDownLatch; 20 import java.util.concurrent.ExecutionException; 21 import java.util.concurrent.Executors; 22 import java.util.concurrent.ExecutorService; 23 import java.util.concurrent.Future; 24 import java.util.concurrent.FutureTask; 25 import java.util.concurrent.LinkedBlockingQueue; 26 import java.util.concurrent.RejectedExecutionException; 27 import java.util.concurrent.RejectedExecutionHandler; 28 import java.util.concurrent.SynchronousQueue; 29 import java.util.concurrent.ThreadFactory; 30 import java.util.concurrent.ThreadPoolExecutor; 31 import java.util.concurrent.TimeUnit; 32 33 import junit.framework.Test; 34 import junit.framework.TestSuite; 35 36 public class ThreadPoolExecutorTest extends JSR166TestCase { 37 // android-note: Removed because the CTS runner does a bad job of 38 // retrying tests that have suite() declarations. 39 // 40 // public static void main(String[] args) { 41 // main(suite(), args); 42 // } 43 // public static Test suite() { 44 // return new TestSuite(...); 45 // } 46 47 static class ExtendedTPE extends ThreadPoolExecutor { 48 final CountDownLatch beforeCalled = new CountDownLatch(1); 49 final CountDownLatch afterCalled = new CountDownLatch(1); 50 final CountDownLatch terminatedCalled = new CountDownLatch(1); 51 52 public ExtendedTPE() { 53 super(1, 1, LONG_DELAY_MS, MILLISECONDS, new SynchronousQueue<Runnable>()); 54 } 55 protected void beforeExecute(Thread t, Runnable r) { 56 beforeCalled.countDown(); 57 } 58 protected void afterExecute(Runnable r, Throwable t) { 59 afterCalled.countDown(); 60 } 61 protected void terminated() { 62 terminatedCalled.countDown(); 63 } 64 65 public boolean beforeCalled() { 66 return beforeCalled.getCount() == 0; 67 } 68 public boolean afterCalled() { 69 return afterCalled.getCount() == 0; 70 } 71 public boolean terminatedCalled() { 72 return terminatedCalled.getCount() == 0; 73 } 74 } 75 76 static class FailingThreadFactory implements ThreadFactory { 77 int calls = 0; 78 public Thread newThread(Runnable r) { 79 if (++calls > 1) return null; 80 return new Thread(r); 81 } 82 } 83 84 /** 85 * execute successfully executes a runnable 86 */ 87 public void testExecute() throws InterruptedException { 88 final ThreadPoolExecutor p = 89 new ThreadPoolExecutor(1, 1, 90 LONG_DELAY_MS, MILLISECONDS, 91 new ArrayBlockingQueue<Runnable>(10)); 92 final CountDownLatch done = new CountDownLatch(1); 93 final Runnable task = new CheckedRunnable() { 94 public void realRun() { 95 done.countDown(); 96 }}; 97 try { 98 p.execute(task); 99 assertTrue(done.await(SMALL_DELAY_MS, MILLISECONDS)); 100 } finally { 101 joinPool(p); 102 } 103 } 104 105 /** 106 * getActiveCount increases but doesn't overestimate, when a 107 * thread becomes active 108 */ 109 public void testGetActiveCount() throws InterruptedException { 110 final ThreadPoolExecutor p = 111 new ThreadPoolExecutor(2, 2, 112 LONG_DELAY_MS, MILLISECONDS, 113 new ArrayBlockingQueue<Runnable>(10)); 114 final CountDownLatch threadStarted = new CountDownLatch(1); 115 final CountDownLatch done = new CountDownLatch(1); 116 try { 117 assertEquals(0, p.getActiveCount()); 118 p.execute(new CheckedRunnable() { 119 public void realRun() throws InterruptedException { 120 threadStarted.countDown(); 121 assertEquals(1, p.getActiveCount()); 122 done.await(); 123 }}); 124 assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS)); 125 assertEquals(1, p.getActiveCount()); 126 } finally { 127 done.countDown(); 128 joinPool(p); 129 } 130 } 131 132 /** 133 * prestartCoreThread starts a thread if under corePoolSize, else doesn't 134 */ 135 public void testPrestartCoreThread() { 136 final ThreadPoolExecutor p = 137 new ThreadPoolExecutor(2, 2, 138 LONG_DELAY_MS, MILLISECONDS, 139 new ArrayBlockingQueue<Runnable>(10)); 140 assertEquals(0, p.getPoolSize()); 141 assertTrue(p.prestartCoreThread()); 142 assertEquals(1, p.getPoolSize()); 143 assertTrue(p.prestartCoreThread()); 144 assertEquals(2, p.getPoolSize()); 145 assertFalse(p.prestartCoreThread()); 146 assertEquals(2, p.getPoolSize()); 147 joinPool(p); 148 } 149 150 /** 151 * prestartAllCoreThreads starts all corePoolSize threads 152 */ 153 public void testPrestartAllCoreThreads() { 154 final ThreadPoolExecutor p = 155 new ThreadPoolExecutor(2, 2, 156 LONG_DELAY_MS, MILLISECONDS, 157 new ArrayBlockingQueue<Runnable>(10)); 158 assertEquals(0, p.getPoolSize()); 159 p.prestartAllCoreThreads(); 160 assertEquals(2, p.getPoolSize()); 161 p.prestartAllCoreThreads(); 162 assertEquals(2, p.getPoolSize()); 163 joinPool(p); 164 } 165 166 /** 167 * getCompletedTaskCount increases, but doesn't overestimate, 168 * when tasks complete 169 */ 170 public void testGetCompletedTaskCount() throws InterruptedException { 171 final ThreadPoolExecutor p = 172 new ThreadPoolExecutor(2, 2, 173 LONG_DELAY_MS, MILLISECONDS, 174 new ArrayBlockingQueue<Runnable>(10)); 175 final CountDownLatch threadStarted = new CountDownLatch(1); 176 final CountDownLatch threadProceed = new CountDownLatch(1); 177 final CountDownLatch threadDone = new CountDownLatch(1); 178 try { 179 assertEquals(0, p.getCompletedTaskCount()); 180 p.execute(new CheckedRunnable() { 181 public void realRun() throws InterruptedException { 182 threadStarted.countDown(); 183 assertEquals(0, p.getCompletedTaskCount()); 184 threadProceed.await(); 185 threadDone.countDown(); 186 }}); 187 await(threadStarted); 188 assertEquals(0, p.getCompletedTaskCount()); 189 threadProceed.countDown(); 190 threadDone.await(); 191 long startTime = System.nanoTime(); 192 while (p.getCompletedTaskCount() != 1) { 193 if (millisElapsedSince(startTime) > LONG_DELAY_MS) 194 fail("timed out"); 195 Thread.yield(); 196 } 197 } finally { 198 joinPool(p); 199 } 200 } 201 202 /** 203 * getCorePoolSize returns size given in constructor if not otherwise set 204 */ 205 public void testGetCorePoolSize() { 206 final ThreadPoolExecutor p = 207 new ThreadPoolExecutor(1, 1, 208 LONG_DELAY_MS, MILLISECONDS, 209 new ArrayBlockingQueue<Runnable>(10)); 210 assertEquals(1, p.getCorePoolSize()); 211 joinPool(p); 212 } 213 214 /** 215 * getKeepAliveTime returns value given in constructor if not otherwise set 216 */ 217 public void testGetKeepAliveTime() { 218 final ThreadPoolExecutor p = 219 new ThreadPoolExecutor(2, 2, 220 1000, MILLISECONDS, 221 new ArrayBlockingQueue<Runnable>(10)); 222 assertEquals(1, p.getKeepAliveTime(TimeUnit.SECONDS)); 223 joinPool(p); 224 } 225 226 /** 227 * getThreadFactory returns factory in constructor if not set 228 */ 229 public void testGetThreadFactory() { 230 ThreadFactory tf = new SimpleThreadFactory(); 231 final ThreadPoolExecutor p = 232 new ThreadPoolExecutor(1, 2, 233 LONG_DELAY_MS, MILLISECONDS, 234 new ArrayBlockingQueue<Runnable>(10), 235 tf, 236 new NoOpREHandler()); 237 assertSame(tf, p.getThreadFactory()); 238 joinPool(p); 239 } 240 241 /** 242 * setThreadFactory sets the thread factory returned by getThreadFactory 243 */ 244 public void testSetThreadFactory() { 245 final ThreadPoolExecutor p = 246 new ThreadPoolExecutor(1, 2, 247 LONG_DELAY_MS, MILLISECONDS, 248 new ArrayBlockingQueue<Runnable>(10)); 249 ThreadFactory tf = new SimpleThreadFactory(); 250 p.setThreadFactory(tf); 251 assertSame(tf, p.getThreadFactory()); 252 joinPool(p); 253 } 254 255 /** 256 * setThreadFactory(null) throws NPE 257 */ 258 public void testSetThreadFactoryNull() { 259 final ThreadPoolExecutor p = 260 new ThreadPoolExecutor(1, 2, 261 LONG_DELAY_MS, MILLISECONDS, 262 new ArrayBlockingQueue<Runnable>(10)); 263 try { 264 p.setThreadFactory(null); 265 shouldThrow(); 266 } catch (NullPointerException success) { 267 } finally { 268 joinPool(p); 269 } 270 } 271 272 /** 273 * getRejectedExecutionHandler returns handler in constructor if not set 274 */ 275 public void testGetRejectedExecutionHandler() { 276 final RejectedExecutionHandler h = new NoOpREHandler(); 277 final ThreadPoolExecutor p = 278 new ThreadPoolExecutor(1, 2, 279 LONG_DELAY_MS, MILLISECONDS, 280 new ArrayBlockingQueue<Runnable>(10), 281 h); 282 assertSame(h, p.getRejectedExecutionHandler()); 283 joinPool(p); 284 } 285 286 /** 287 * setRejectedExecutionHandler sets the handler returned by 288 * getRejectedExecutionHandler 289 */ 290 public void testSetRejectedExecutionHandler() { 291 final ThreadPoolExecutor p = 292 new ThreadPoolExecutor(1, 2, 293 LONG_DELAY_MS, MILLISECONDS, 294 new ArrayBlockingQueue<Runnable>(10)); 295 RejectedExecutionHandler h = new NoOpREHandler(); 296 p.setRejectedExecutionHandler(h); 297 assertSame(h, p.getRejectedExecutionHandler()); 298 joinPool(p); 299 } 300 301 /** 302 * setRejectedExecutionHandler(null) throws NPE 303 */ 304 public void testSetRejectedExecutionHandlerNull() { 305 final ThreadPoolExecutor p = 306 new ThreadPoolExecutor(1, 2, 307 LONG_DELAY_MS, MILLISECONDS, 308 new ArrayBlockingQueue<Runnable>(10)); 309 try { 310 p.setRejectedExecutionHandler(null); 311 shouldThrow(); 312 } catch (NullPointerException success) { 313 } finally { 314 joinPool(p); 315 } 316 } 317 318 /** 319 * getLargestPoolSize increases, but doesn't overestimate, when 320 * multiple threads active 321 */ 322 public void testGetLargestPoolSize() throws InterruptedException { 323 final int THREADS = 3; 324 final ThreadPoolExecutor p = 325 new ThreadPoolExecutor(THREADS, THREADS, 326 LONG_DELAY_MS, MILLISECONDS, 327 new ArrayBlockingQueue<Runnable>(10)); 328 final CountDownLatch threadsStarted = new CountDownLatch(THREADS); 329 final CountDownLatch done = new CountDownLatch(1); 330 try { 331 assertEquals(0, p.getLargestPoolSize()); 332 for (int i = 0; i < THREADS; i++) 333 p.execute(new CheckedRunnable() { 334 public void realRun() throws InterruptedException { 335 threadsStarted.countDown(); 336 done.await(); 337 assertEquals(THREADS, p.getLargestPoolSize()); 338 }}); 339 assertTrue(threadsStarted.await(SMALL_DELAY_MS, MILLISECONDS)); 340 assertEquals(THREADS, p.getLargestPoolSize()); 341 } finally { 342 done.countDown(); 343 joinPool(p); 344 assertEquals(THREADS, p.getLargestPoolSize()); 345 } 346 } 347 348 /** 349 * getMaximumPoolSize returns value given in constructor if not 350 * otherwise set 351 */ 352 public void testGetMaximumPoolSize() { 353 final ThreadPoolExecutor p = 354 new ThreadPoolExecutor(2, 3, 355 LONG_DELAY_MS, MILLISECONDS, 356 new ArrayBlockingQueue<Runnable>(10)); 357 assertEquals(3, p.getMaximumPoolSize()); 358 joinPool(p); 359 } 360 361 /** 362 * getPoolSize increases, but doesn't overestimate, when threads 363 * become active 364 */ 365 public void testGetPoolSize() throws InterruptedException { 366 final ThreadPoolExecutor p = 367 new ThreadPoolExecutor(1, 1, 368 LONG_DELAY_MS, MILLISECONDS, 369 new ArrayBlockingQueue<Runnable>(10)); 370 final CountDownLatch threadStarted = new CountDownLatch(1); 371 final CountDownLatch done = new CountDownLatch(1); 372 try { 373 assertEquals(0, p.getPoolSize()); 374 p.execute(new CheckedRunnable() { 375 public void realRun() throws InterruptedException { 376 threadStarted.countDown(); 377 assertEquals(1, p.getPoolSize()); 378 done.await(); 379 }}); 380 assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS)); 381 assertEquals(1, p.getPoolSize()); 382 } finally { 383 done.countDown(); 384 joinPool(p); 385 } 386 } 387 388 /** 389 * getTaskCount increases, but doesn't overestimate, when tasks submitted 390 */ 391 public void testGetTaskCount() throws InterruptedException { 392 final ThreadPoolExecutor p = 393 new ThreadPoolExecutor(1, 1, 394 LONG_DELAY_MS, MILLISECONDS, 395 new ArrayBlockingQueue<Runnable>(10)); 396 final CountDownLatch threadStarted = new CountDownLatch(1); 397 final CountDownLatch done = new CountDownLatch(1); 398 try { 399 assertEquals(0, p.getTaskCount()); 400 p.execute(new CheckedRunnable() { 401 public void realRun() throws InterruptedException { 402 threadStarted.countDown(); 403 assertEquals(1, p.getTaskCount()); 404 done.await(); 405 }}); 406 assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS)); 407 assertEquals(1, p.getTaskCount()); 408 } finally { 409 done.countDown(); 410 joinPool(p); 411 } 412 } 413 414 /** 415 * isShutdown is false before shutdown, true after 416 */ 417 public void testIsShutdown() { 418 final ThreadPoolExecutor p = 419 new ThreadPoolExecutor(1, 1, 420 LONG_DELAY_MS, MILLISECONDS, 421 new ArrayBlockingQueue<Runnable>(10)); 422 assertFalse(p.isShutdown()); 423 try { p.shutdown(); } catch (SecurityException ok) { return; } 424 assertTrue(p.isShutdown()); 425 joinPool(p); 426 } 427 428 /** 429 * awaitTermination on a non-shutdown pool times out 430 */ 431 public void testAwaitTermination_timesOut() throws InterruptedException { 432 final ThreadPoolExecutor p = 433 new ThreadPoolExecutor(1, 1, 434 LONG_DELAY_MS, MILLISECONDS, 435 new ArrayBlockingQueue<Runnable>(10)); 436 assertFalse(p.isTerminated()); 437 assertFalse(p.awaitTermination(Long.MIN_VALUE, NANOSECONDS)); 438 assertFalse(p.awaitTermination(Long.MIN_VALUE, MILLISECONDS)); 439 assertFalse(p.awaitTermination(-1L, NANOSECONDS)); 440 assertFalse(p.awaitTermination(-1L, MILLISECONDS)); 441 assertFalse(p.awaitTermination(0L, NANOSECONDS)); 442 assertFalse(p.awaitTermination(0L, MILLISECONDS)); 443 long timeoutNanos = 999999L; 444 long startTime = System.nanoTime(); 445 assertFalse(p.awaitTermination(timeoutNanos, NANOSECONDS)); 446 assertTrue(System.nanoTime() - startTime >= timeoutNanos); 447 assertFalse(p.isTerminated()); 448 startTime = System.nanoTime(); 449 long timeoutMillis = timeoutMillis(); 450 assertFalse(p.awaitTermination(timeoutMillis, MILLISECONDS)); 451 assertTrue(millisElapsedSince(startTime) >= timeoutMillis); 452 assertFalse(p.isTerminated()); 453 p.shutdown(); 454 assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); 455 assertTrue(p.isTerminated()); 456 } 457 458 /** 459 * isTerminated is false before termination, true after 460 */ 461 public void testIsTerminated() throws InterruptedException { 462 final ThreadPoolExecutor p = 463 new ThreadPoolExecutor(1, 1, 464 LONG_DELAY_MS, MILLISECONDS, 465 new ArrayBlockingQueue<Runnable>(10)); 466 final CountDownLatch threadStarted = new CountDownLatch(1); 467 final CountDownLatch done = new CountDownLatch(1); 468 assertFalse(p.isTerminated()); 469 try { 470 p.execute(new CheckedRunnable() { 471 public void realRun() throws InterruptedException { 472 assertFalse(p.isTerminated()); 473 threadStarted.countDown(); 474 done.await(); 475 }}); 476 assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS)); 477 assertFalse(p.isTerminating()); 478 done.countDown(); 479 } finally { 480 try { p.shutdown(); } catch (SecurityException ok) { return; } 481 } 482 assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); 483 assertTrue(p.isTerminated()); 484 } 485 486 /** 487 * isTerminating is not true when running or when terminated 488 */ 489 public void testIsTerminating() throws InterruptedException { 490 final ThreadPoolExecutor p = 491 new ThreadPoolExecutor(1, 1, 492 LONG_DELAY_MS, MILLISECONDS, 493 new ArrayBlockingQueue<Runnable>(10)); 494 final CountDownLatch threadStarted = new CountDownLatch(1); 495 final CountDownLatch done = new CountDownLatch(1); 496 try { 497 assertFalse(p.isTerminating()); 498 p.execute(new CheckedRunnable() { 499 public void realRun() throws InterruptedException { 500 assertFalse(p.isTerminating()); 501 threadStarted.countDown(); 502 done.await(); 503 }}); 504 assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS)); 505 assertFalse(p.isTerminating()); 506 done.countDown(); 507 } finally { 508 try { p.shutdown(); } catch (SecurityException ok) { return; } 509 } 510 assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); 511 assertTrue(p.isTerminated()); 512 assertFalse(p.isTerminating()); 513 } 514 515 /** 516 * getQueue returns the work queue, which contains queued tasks 517 */ 518 public void testGetQueue() throws InterruptedException { 519 final BlockingQueue<Runnable> q = new ArrayBlockingQueue<Runnable>(10); 520 final ThreadPoolExecutor p = 521 new ThreadPoolExecutor(1, 1, 522 LONG_DELAY_MS, MILLISECONDS, 523 q); 524 final CountDownLatch threadStarted = new CountDownLatch(1); 525 final CountDownLatch done = new CountDownLatch(1); 526 try { 527 FutureTask[] tasks = new FutureTask[5]; 528 for (int i = 0; i < tasks.length; i++) { 529 Callable task = new CheckedCallable<Boolean>() { 530 public Boolean realCall() throws InterruptedException { 531 threadStarted.countDown(); 532 assertSame(q, p.getQueue()); 533 done.await(); 534 return Boolean.TRUE; 535 }}; 536 tasks[i] = new FutureTask(task); 537 p.execute(tasks[i]); 538 } 539 assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS)); 540 assertSame(q, p.getQueue()); 541 assertFalse(q.contains(tasks[0])); 542 assertTrue(q.contains(tasks[tasks.length - 1])); 543 assertEquals(tasks.length - 1, q.size()); 544 } finally { 545 done.countDown(); 546 joinPool(p); 547 } 548 } 549 550 /** 551 * remove(task) removes queued task, and fails to remove active task 552 */ 553 public void testRemove() throws InterruptedException { 554 BlockingQueue<Runnable> q = new ArrayBlockingQueue<Runnable>(10); 555 final ThreadPoolExecutor p = 556 new ThreadPoolExecutor(1, 1, 557 LONG_DELAY_MS, MILLISECONDS, 558 q); 559 Runnable[] tasks = new Runnable[5]; 560 final CountDownLatch threadStarted = new CountDownLatch(1); 561 final CountDownLatch done = new CountDownLatch(1); 562 try { 563 for (int i = 0; i < tasks.length; i++) { 564 tasks[i] = new CheckedRunnable() { 565 public void realRun() throws InterruptedException { 566 threadStarted.countDown(); 567 done.await(); 568 }}; 569 p.execute(tasks[i]); 570 } 571 assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS)); 572 assertFalse(p.remove(tasks[0])); 573 assertTrue(q.contains(tasks[4])); 574 assertTrue(q.contains(tasks[3])); 575 assertTrue(p.remove(tasks[4])); 576 assertFalse(p.remove(tasks[4])); 577 assertFalse(q.contains(tasks[4])); 578 assertTrue(q.contains(tasks[3])); 579 assertTrue(p.remove(tasks[3])); 580 assertFalse(q.contains(tasks[3])); 581 } finally { 582 done.countDown(); 583 joinPool(p); 584 } 585 } 586 587 /** 588 * purge removes cancelled tasks from the queue 589 */ 590 public void testPurge() throws InterruptedException { 591 final CountDownLatch threadStarted = new CountDownLatch(1); 592 final CountDownLatch done = new CountDownLatch(1); 593 final BlockingQueue<Runnable> q = new ArrayBlockingQueue<Runnable>(10); 594 final ThreadPoolExecutor p = 595 new ThreadPoolExecutor(1, 1, 596 LONG_DELAY_MS, MILLISECONDS, 597 q); 598 FutureTask[] tasks = new FutureTask[5]; 599 try { 600 for (int i = 0; i < tasks.length; i++) { 601 Callable task = new CheckedCallable<Boolean>() { 602 public Boolean realCall() throws InterruptedException { 603 threadStarted.countDown(); 604 done.await(); 605 return Boolean.TRUE; 606 }}; 607 tasks[i] = new FutureTask(task); 608 p.execute(tasks[i]); 609 } 610 assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS)); 611 assertEquals(tasks.length, p.getTaskCount()); 612 assertEquals(tasks.length - 1, q.size()); 613 assertEquals(1L, p.getActiveCount()); 614 assertEquals(0L, p.getCompletedTaskCount()); 615 tasks[4].cancel(true); 616 tasks[3].cancel(false); 617 p.purge(); 618 assertEquals(tasks.length - 3, q.size()); 619 assertEquals(tasks.length - 2, p.getTaskCount()); 620 p.purge(); // Nothing to do 621 assertEquals(tasks.length - 3, q.size()); 622 assertEquals(tasks.length - 2, p.getTaskCount()); 623 } finally { 624 done.countDown(); 625 joinPool(p); 626 } 627 } 628 629 /** 630 * shutdownNow returns a list containing tasks that were not run 631 */ 632 public void testShutdownNow() { 633 final ThreadPoolExecutor p = 634 new ThreadPoolExecutor(1, 1, 635 LONG_DELAY_MS, MILLISECONDS, 636 new ArrayBlockingQueue<Runnable>(10)); 637 List l; 638 try { 639 for (int i = 0; i < 5; i++) 640 p.execute(new MediumPossiblyInterruptedRunnable()); 641 } 642 finally { 643 try { 644 l = p.shutdownNow(); 645 } catch (SecurityException ok) { return; } 646 } 647 assertTrue(p.isShutdown()); 648 assertTrue(l.size() <= 4); 649 } 650 651 // Exception Tests 652 653 /** 654 * Constructor throws if corePoolSize argument is less than zero 655 */ 656 public void testConstructor1() { 657 try { 658 new ThreadPoolExecutor(-1, 1, 659 LONG_DELAY_MS, MILLISECONDS, 660 new ArrayBlockingQueue<Runnable>(10)); 661 shouldThrow(); 662 } catch (IllegalArgumentException success) {} 663 } 664 665 /** 666 * Constructor throws if maximumPoolSize is less than zero 667 */ 668 public void testConstructor2() { 669 try { 670 new ThreadPoolExecutor(1, -1, 671 LONG_DELAY_MS, MILLISECONDS, 672 new ArrayBlockingQueue<Runnable>(10)); 673 shouldThrow(); 674 } catch (IllegalArgumentException success) {} 675 } 676 677 /** 678 * Constructor throws if maximumPoolSize is equal to zero 679 */ 680 public void testConstructor3() { 681 try { 682 new ThreadPoolExecutor(1, 0, 683 LONG_DELAY_MS, MILLISECONDS, 684 new ArrayBlockingQueue<Runnable>(10)); 685 shouldThrow(); 686 } catch (IllegalArgumentException success) {} 687 } 688 689 /** 690 * Constructor throws if keepAliveTime is less than zero 691 */ 692 public void testConstructor4() { 693 try { 694 new ThreadPoolExecutor(1, 2, 695 -1L, MILLISECONDS, 696 new ArrayBlockingQueue<Runnable>(10)); 697 shouldThrow(); 698 } catch (IllegalArgumentException success) {} 699 } 700 701 /** 702 * Constructor throws if corePoolSize is greater than the maximumPoolSize 703 */ 704 public void testConstructor5() { 705 try { 706 new ThreadPoolExecutor(2, 1, 707 LONG_DELAY_MS, MILLISECONDS, 708 new ArrayBlockingQueue<Runnable>(10)); 709 shouldThrow(); 710 } catch (IllegalArgumentException success) {} 711 } 712 713 /** 714 * Constructor throws if workQueue is set to null 715 */ 716 public void testConstructorNullPointerException() { 717 try { 718 new ThreadPoolExecutor(1, 2, 719 LONG_DELAY_MS, MILLISECONDS, 720 (BlockingQueue) null); 721 shouldThrow(); 722 } catch (NullPointerException success) {} 723 } 724 725 /** 726 * Constructor throws if corePoolSize argument is less than zero 727 */ 728 public void testConstructor6() { 729 try { 730 new ThreadPoolExecutor(-1, 1, 731 LONG_DELAY_MS, MILLISECONDS, 732 new ArrayBlockingQueue<Runnable>(10), 733 new SimpleThreadFactory()); 734 shouldThrow(); 735 } catch (IllegalArgumentException success) {} 736 } 737 738 /** 739 * Constructor throws if maximumPoolSize is less than zero 740 */ 741 public void testConstructor7() { 742 try { 743 new ThreadPoolExecutor(1, -1, 744 LONG_DELAY_MS, MILLISECONDS, 745 new ArrayBlockingQueue<Runnable>(10), 746 new SimpleThreadFactory()); 747 shouldThrow(); 748 } catch (IllegalArgumentException success) {} 749 } 750 751 /** 752 * Constructor throws if maximumPoolSize is equal to zero 753 */ 754 public void testConstructor8() { 755 try { 756 new ThreadPoolExecutor(1, 0, 757 LONG_DELAY_MS, MILLISECONDS, 758 new ArrayBlockingQueue<Runnable>(10), 759 new SimpleThreadFactory()); 760 shouldThrow(); 761 } catch (IllegalArgumentException success) {} 762 } 763 764 /** 765 * Constructor throws if keepAliveTime is less than zero 766 */ 767 public void testConstructor9() { 768 try { 769 new ThreadPoolExecutor(1, 2, 770 -1L, MILLISECONDS, 771 new ArrayBlockingQueue<Runnable>(10), 772 new SimpleThreadFactory()); 773 shouldThrow(); 774 } catch (IllegalArgumentException success) {} 775 } 776 777 /** 778 * Constructor throws if corePoolSize is greater than the maximumPoolSize 779 */ 780 public void testConstructor10() { 781 try { 782 new ThreadPoolExecutor(2, 1, 783 LONG_DELAY_MS, MILLISECONDS, 784 new ArrayBlockingQueue<Runnable>(10), 785 new SimpleThreadFactory()); 786 shouldThrow(); 787 } catch (IllegalArgumentException success) {} 788 } 789 790 /** 791 * Constructor throws if workQueue is set to null 792 */ 793 public void testConstructorNullPointerException2() { 794 try { 795 new ThreadPoolExecutor(1, 2, 796 LONG_DELAY_MS, MILLISECONDS, 797 (BlockingQueue) null, 798 new SimpleThreadFactory()); 799 shouldThrow(); 800 } catch (NullPointerException success) {} 801 } 802 803 /** 804 * Constructor throws if threadFactory is set to null 805 */ 806 public void testConstructorNullPointerException3() { 807 try { 808 new ThreadPoolExecutor(1, 2, 809 LONG_DELAY_MS, MILLISECONDS, 810 new ArrayBlockingQueue<Runnable>(10), 811 (ThreadFactory) null); 812 shouldThrow(); 813 } catch (NullPointerException success) {} 814 } 815 816 /** 817 * Constructor throws if corePoolSize argument is less than zero 818 */ 819 public void testConstructor11() { 820 try { 821 new ThreadPoolExecutor(-1, 1, 822 LONG_DELAY_MS, MILLISECONDS, 823 new ArrayBlockingQueue<Runnable>(10), 824 new NoOpREHandler()); 825 shouldThrow(); 826 } catch (IllegalArgumentException success) {} 827 } 828 829 /** 830 * Constructor throws if maximumPoolSize is less than zero 831 */ 832 public void testConstructor12() { 833 try { 834 new ThreadPoolExecutor(1, -1, 835 LONG_DELAY_MS, MILLISECONDS, 836 new ArrayBlockingQueue<Runnable>(10), 837 new NoOpREHandler()); 838 shouldThrow(); 839 } catch (IllegalArgumentException success) {} 840 } 841 842 /** 843 * Constructor throws if maximumPoolSize is equal to zero 844 */ 845 public void testConstructor13() { 846 try { 847 new ThreadPoolExecutor(1, 0, 848 LONG_DELAY_MS, MILLISECONDS, 849 new ArrayBlockingQueue<Runnable>(10), 850 new NoOpREHandler()); 851 shouldThrow(); 852 } catch (IllegalArgumentException success) {} 853 } 854 855 /** 856 * Constructor throws if keepAliveTime is less than zero 857 */ 858 public void testConstructor14() { 859 try { 860 new ThreadPoolExecutor(1, 2, 861 -1L, MILLISECONDS, 862 new ArrayBlockingQueue<Runnable>(10), 863 new NoOpREHandler()); 864 shouldThrow(); 865 } catch (IllegalArgumentException success) {} 866 } 867 868 /** 869 * Constructor throws if corePoolSize is greater than the maximumPoolSize 870 */ 871 public void testConstructor15() { 872 try { 873 new ThreadPoolExecutor(2, 1, 874 LONG_DELAY_MS, MILLISECONDS, 875 new ArrayBlockingQueue<Runnable>(10), 876 new NoOpREHandler()); 877 shouldThrow(); 878 } catch (IllegalArgumentException success) {} 879 } 880 881 /** 882 * Constructor throws if workQueue is set to null 883 */ 884 public void testConstructorNullPointerException4() { 885 try { 886 new ThreadPoolExecutor(1, 2, 887 LONG_DELAY_MS, MILLISECONDS, 888 (BlockingQueue) null, 889 new NoOpREHandler()); 890 shouldThrow(); 891 } catch (NullPointerException success) {} 892 } 893 894 /** 895 * Constructor throws if handler is set to null 896 */ 897 public void testConstructorNullPointerException5() { 898 try { 899 new ThreadPoolExecutor(1, 2, 900 LONG_DELAY_MS, MILLISECONDS, 901 new ArrayBlockingQueue<Runnable>(10), 902 (RejectedExecutionHandler) null); 903 shouldThrow(); 904 } catch (NullPointerException success) {} 905 } 906 907 /** 908 * Constructor throws if corePoolSize argument is less than zero 909 */ 910 public void testConstructor16() { 911 try { 912 new ThreadPoolExecutor(-1, 1, 913 LONG_DELAY_MS, MILLISECONDS, 914 new ArrayBlockingQueue<Runnable>(10), 915 new SimpleThreadFactory(), 916 new NoOpREHandler()); 917 shouldThrow(); 918 } catch (IllegalArgumentException success) {} 919 } 920 921 /** 922 * Constructor throws if maximumPoolSize is less than zero 923 */ 924 public void testConstructor17() { 925 try { 926 new ThreadPoolExecutor(1, -1, 927 LONG_DELAY_MS, MILLISECONDS, 928 new ArrayBlockingQueue<Runnable>(10), 929 new SimpleThreadFactory(), 930 new NoOpREHandler()); 931 shouldThrow(); 932 } catch (IllegalArgumentException success) {} 933 } 934 935 /** 936 * Constructor throws if maximumPoolSize is equal to zero 937 */ 938 public void testConstructor18() { 939 try { 940 new ThreadPoolExecutor(1, 0, 941 LONG_DELAY_MS, MILLISECONDS, 942 new ArrayBlockingQueue<Runnable>(10), 943 new SimpleThreadFactory(), 944 new NoOpREHandler()); 945 shouldThrow(); 946 } catch (IllegalArgumentException success) {} 947 } 948 949 /** 950 * Constructor throws if keepAliveTime is less than zero 951 */ 952 public void testConstructor19() { 953 try { 954 new ThreadPoolExecutor(1, 2, 955 -1L, MILLISECONDS, 956 new ArrayBlockingQueue<Runnable>(10), 957 new SimpleThreadFactory(), 958 new NoOpREHandler()); 959 shouldThrow(); 960 } catch (IllegalArgumentException success) {} 961 } 962 963 /** 964 * Constructor throws if corePoolSize is greater than the maximumPoolSize 965 */ 966 public void testConstructor20() { 967 try { 968 new ThreadPoolExecutor(2, 1, 969 LONG_DELAY_MS, MILLISECONDS, 970 new ArrayBlockingQueue<Runnable>(10), 971 new SimpleThreadFactory(), 972 new NoOpREHandler()); 973 shouldThrow(); 974 } catch (IllegalArgumentException success) {} 975 } 976 977 /** 978 * Constructor throws if workQueue is null 979 */ 980 public void testConstructorNullPointerException6() { 981 try { 982 new ThreadPoolExecutor(1, 2, 983 LONG_DELAY_MS, MILLISECONDS, 984 (BlockingQueue) null, 985 new SimpleThreadFactory(), 986 new NoOpREHandler()); 987 shouldThrow(); 988 } catch (NullPointerException success) {} 989 } 990 991 /** 992 * Constructor throws if handler is null 993 */ 994 public void testConstructorNullPointerException7() { 995 try { 996 new ThreadPoolExecutor(1, 2, 997 LONG_DELAY_MS, MILLISECONDS, 998 new ArrayBlockingQueue<Runnable>(10), 999 new SimpleThreadFactory(), 1000 (RejectedExecutionHandler) null); 1001 shouldThrow(); 1002 } catch (NullPointerException success) {} 1003 } 1004 1005 /** 1006 * Constructor throws if ThreadFactory is null 1007 */ 1008 public void testConstructorNullPointerException8() { 1009 try { 1010 new ThreadPoolExecutor(1, 2, 1011 LONG_DELAY_MS, MILLISECONDS, 1012 new ArrayBlockingQueue<Runnable>(10), 1013 (ThreadFactory) null, 1014 new NoOpREHandler()); 1015 shouldThrow(); 1016 } catch (NullPointerException success) {} 1017 } 1018 1019 /** 1020 * get of submitted callable throws InterruptedException if interrupted 1021 */ 1022 public void testInterruptedSubmit() throws InterruptedException { 1023 final ThreadPoolExecutor p = 1024 new ThreadPoolExecutor(1, 1, 1025 60, TimeUnit.SECONDS, 1026 new ArrayBlockingQueue<Runnable>(10)); 1027 1028 final CountDownLatch threadStarted = new CountDownLatch(1); 1029 final CountDownLatch done = new CountDownLatch(1); 1030 try { 1031 Thread t = newStartedThread(new CheckedInterruptedRunnable() { 1032 public void realRun() throws Exception { 1033 Callable task = new CheckedCallable<Boolean>() { 1034 public Boolean realCall() throws InterruptedException { 1035 threadStarted.countDown(); 1036 done.await(); 1037 return Boolean.TRUE; 1038 }}; 1039 p.submit(task).get(); 1040 }}); 1041 1042 assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS)); 1043 t.interrupt(); 1044 awaitTermination(t, MEDIUM_DELAY_MS); 1045 } finally { 1046 done.countDown(); 1047 joinPool(p); 1048 } 1049 } 1050 1051 /** 1052 * execute throws RejectedExecutionException if saturated. 1053 */ 1054 public void testSaturatedExecute() { 1055 ThreadPoolExecutor p = 1056 new ThreadPoolExecutor(1, 1, 1057 LONG_DELAY_MS, MILLISECONDS, 1058 new ArrayBlockingQueue<Runnable>(1)); 1059 final CountDownLatch done = new CountDownLatch(1); 1060 try { 1061 Runnable task = new CheckedRunnable() { 1062 public void realRun() throws InterruptedException { 1063 done.await(); 1064 }}; 1065 for (int i = 0; i < 2; ++i) 1066 p.execute(task); 1067 for (int i = 0; i < 2; ++i) { 1068 try { 1069 p.execute(task); 1070 shouldThrow(); 1071 } catch (RejectedExecutionException success) {} 1072 assertTrue(p.getTaskCount() <= 2); 1073 } 1074 } finally { 1075 done.countDown(); 1076 joinPool(p); 1077 } 1078 } 1079 1080 /** 1081 * submit(runnable) throws RejectedExecutionException if saturated. 1082 */ 1083 public void testSaturatedSubmitRunnable() { 1084 ThreadPoolExecutor p = 1085 new ThreadPoolExecutor(1, 1, 1086 LONG_DELAY_MS, MILLISECONDS, 1087 new ArrayBlockingQueue<Runnable>(1)); 1088 final CountDownLatch done = new CountDownLatch(1); 1089 try { 1090 Runnable task = new CheckedRunnable() { 1091 public void realRun() throws InterruptedException { 1092 done.await(); 1093 }}; 1094 for (int i = 0; i < 2; ++i) 1095 p.submit(task); 1096 for (int i = 0; i < 2; ++i) { 1097 try { 1098 p.execute(task); 1099 shouldThrow(); 1100 } catch (RejectedExecutionException success) {} 1101 assertTrue(p.getTaskCount() <= 2); 1102 } 1103 } finally { 1104 done.countDown(); 1105 joinPool(p); 1106 } 1107 } 1108 1109 /** 1110 * submit(callable) throws RejectedExecutionException if saturated. 1111 */ 1112 public void testSaturatedSubmitCallable() { 1113 ThreadPoolExecutor p = 1114 new ThreadPoolExecutor(1, 1, 1115 LONG_DELAY_MS, MILLISECONDS, 1116 new ArrayBlockingQueue<Runnable>(1)); 1117 final CountDownLatch done = new CountDownLatch(1); 1118 try { 1119 Runnable task = new CheckedRunnable() { 1120 public void realRun() throws InterruptedException { 1121 done.await(); 1122 }}; 1123 for (int i = 0; i < 2; ++i) 1124 p.submit(Executors.callable(task)); 1125 for (int i = 0; i < 2; ++i) { 1126 try { 1127 p.execute(task); 1128 shouldThrow(); 1129 } catch (RejectedExecutionException success) {} 1130 assertTrue(p.getTaskCount() <= 2); 1131 } 1132 } finally { 1133 done.countDown(); 1134 joinPool(p); 1135 } 1136 } 1137 1138 /** 1139 * executor using CallerRunsPolicy runs task if saturated. 1140 */ 1141 public void testSaturatedExecute2() { 1142 RejectedExecutionHandler h = new ThreadPoolExecutor.CallerRunsPolicy(); 1143 final ThreadPoolExecutor p = 1144 new ThreadPoolExecutor(1, 1, 1145 LONG_DELAY_MS, 1146 MILLISECONDS, 1147 new ArrayBlockingQueue<Runnable>(1), 1148 h); 1149 try { 1150 TrackedNoOpRunnable[] tasks = new TrackedNoOpRunnable[5]; 1151 for (int i = 0; i < tasks.length; ++i) 1152 tasks[i] = new TrackedNoOpRunnable(); 1153 TrackedLongRunnable mr = new TrackedLongRunnable(); 1154 p.execute(mr); 1155 for (int i = 0; i < tasks.length; ++i) 1156 p.execute(tasks[i]); 1157 for (int i = 1; i < tasks.length; ++i) 1158 assertTrue(tasks[i].done); 1159 try { p.shutdownNow(); } catch (SecurityException ok) { return; } 1160 } finally { 1161 joinPool(p); 1162 } 1163 } 1164 1165 /** 1166 * executor using DiscardPolicy drops task if saturated. 1167 */ 1168 public void testSaturatedExecute3() { 1169 RejectedExecutionHandler h = new ThreadPoolExecutor.DiscardPolicy(); 1170 final ThreadPoolExecutor p = 1171 new ThreadPoolExecutor(1, 1, 1172 LONG_DELAY_MS, MILLISECONDS, 1173 new ArrayBlockingQueue<Runnable>(1), 1174 h); 1175 try { 1176 TrackedNoOpRunnable[] tasks = new TrackedNoOpRunnable[5]; 1177 for (int i = 0; i < tasks.length; ++i) 1178 tasks[i] = new TrackedNoOpRunnable(); 1179 p.execute(new TrackedLongRunnable()); 1180 for (TrackedNoOpRunnable task : tasks) 1181 p.execute(task); 1182 for (TrackedNoOpRunnable task : tasks) 1183 assertFalse(task.done); 1184 try { p.shutdownNow(); } catch (SecurityException ok) { return; } 1185 } finally { 1186 joinPool(p); 1187 } 1188 } 1189 1190 /** 1191 * executor using DiscardOldestPolicy drops oldest task if saturated. 1192 */ 1193 public void testSaturatedExecute4() { 1194 RejectedExecutionHandler h = new ThreadPoolExecutor.DiscardOldestPolicy(); 1195 final ThreadPoolExecutor p = 1196 new ThreadPoolExecutor(1, 1, 1197 LONG_DELAY_MS, MILLISECONDS, 1198 new ArrayBlockingQueue<Runnable>(1), 1199 h); 1200 try { 1201 p.execute(new TrackedLongRunnable()); 1202 TrackedLongRunnable r2 = new TrackedLongRunnable(); 1203 p.execute(r2); 1204 assertTrue(p.getQueue().contains(r2)); 1205 TrackedNoOpRunnable r3 = new TrackedNoOpRunnable(); 1206 p.execute(r3); 1207 assertFalse(p.getQueue().contains(r2)); 1208 assertTrue(p.getQueue().contains(r3)); 1209 try { p.shutdownNow(); } catch (SecurityException ok) { return; } 1210 } finally { 1211 joinPool(p); 1212 } 1213 } 1214 1215 /** 1216 * execute throws RejectedExecutionException if shutdown 1217 */ 1218 public void testRejectedExecutionExceptionOnShutdown() { 1219 ThreadPoolExecutor p = 1220 new ThreadPoolExecutor(1, 1, 1221 LONG_DELAY_MS, MILLISECONDS, 1222 new ArrayBlockingQueue<Runnable>(1)); 1223 try { p.shutdown(); } catch (SecurityException ok) { return; } 1224 try { 1225 p.execute(new NoOpRunnable()); 1226 shouldThrow(); 1227 } catch (RejectedExecutionException success) {} 1228 1229 joinPool(p); 1230 } 1231 1232 /** 1233 * execute using CallerRunsPolicy drops task on shutdown 1234 */ 1235 public void testCallerRunsOnShutdown() { 1236 RejectedExecutionHandler h = new ThreadPoolExecutor.CallerRunsPolicy(); 1237 final ThreadPoolExecutor p = 1238 new ThreadPoolExecutor(1, 1, 1239 LONG_DELAY_MS, MILLISECONDS, 1240 new ArrayBlockingQueue<Runnable>(1), h); 1241 1242 try { p.shutdown(); } catch (SecurityException ok) { return; } 1243 try { 1244 TrackedNoOpRunnable r = new TrackedNoOpRunnable(); 1245 p.execute(r); 1246 assertFalse(r.done); 1247 } finally { 1248 joinPool(p); 1249 } 1250 } 1251 1252 /** 1253 * execute using DiscardPolicy drops task on shutdown 1254 */ 1255 public void testDiscardOnShutdown() { 1256 RejectedExecutionHandler h = new ThreadPoolExecutor.DiscardPolicy(); 1257 ThreadPoolExecutor p = 1258 new ThreadPoolExecutor(1, 1, 1259 LONG_DELAY_MS, MILLISECONDS, 1260 new ArrayBlockingQueue<Runnable>(1), 1261 h); 1262 1263 try { p.shutdown(); } catch (SecurityException ok) { return; } 1264 try { 1265 TrackedNoOpRunnable r = new TrackedNoOpRunnable(); 1266 p.execute(r); 1267 assertFalse(r.done); 1268 } finally { 1269 joinPool(p); 1270 } 1271 } 1272 1273 /** 1274 * execute using DiscardOldestPolicy drops task on shutdown 1275 */ 1276 public void testDiscardOldestOnShutdown() { 1277 RejectedExecutionHandler h = new ThreadPoolExecutor.DiscardOldestPolicy(); 1278 ThreadPoolExecutor p = 1279 new ThreadPoolExecutor(1, 1, 1280 LONG_DELAY_MS, MILLISECONDS, 1281 new ArrayBlockingQueue<Runnable>(1), 1282 h); 1283 1284 try { p.shutdown(); } catch (SecurityException ok) { return; } 1285 try { 1286 TrackedNoOpRunnable r = new TrackedNoOpRunnable(); 1287 p.execute(r); 1288 assertFalse(r.done); 1289 } finally { 1290 joinPool(p); 1291 } 1292 } 1293 1294 /** 1295 * execute(null) throws NPE 1296 */ 1297 public void testExecuteNull() { 1298 ThreadPoolExecutor p = 1299 new ThreadPoolExecutor(1, 2, 1300 LONG_DELAY_MS, MILLISECONDS, 1301 new ArrayBlockingQueue<Runnable>(10)); 1302 try { 1303 p.execute(null); 1304 shouldThrow(); 1305 } catch (NullPointerException success) {} 1306 1307 joinPool(p); 1308 } 1309 1310 /** 1311 * setCorePoolSize of negative value throws IllegalArgumentException 1312 */ 1313 public void testCorePoolSizeIllegalArgumentException() { 1314 ThreadPoolExecutor p = 1315 new ThreadPoolExecutor(1, 2, 1316 LONG_DELAY_MS, MILLISECONDS, 1317 new ArrayBlockingQueue<Runnable>(10)); 1318 try { 1319 p.setCorePoolSize(-1); 1320 shouldThrow(); 1321 } catch (IllegalArgumentException success) { 1322 } finally { 1323 try { p.shutdown(); } catch (SecurityException ok) { return; } 1324 } 1325 joinPool(p); 1326 } 1327 1328 /** 1329 * setMaximumPoolSize(int) throws IllegalArgumentException if 1330 * given a value less the core pool size 1331 */ 1332 public void testMaximumPoolSizeIllegalArgumentException() { 1333 ThreadPoolExecutor p = 1334 new ThreadPoolExecutor(2, 3, 1335 LONG_DELAY_MS, MILLISECONDS, 1336 new ArrayBlockingQueue<Runnable>(10)); 1337 try { 1338 p.setMaximumPoolSize(1); 1339 shouldThrow(); 1340 } catch (IllegalArgumentException success) { 1341 } finally { 1342 try { p.shutdown(); } catch (SecurityException ok) { return; } 1343 } 1344 joinPool(p); 1345 } 1346 1347 /** 1348 * setMaximumPoolSize throws IllegalArgumentException 1349 * if given a negative value 1350 */ 1351 public void testMaximumPoolSizeIllegalArgumentException2() { 1352 ThreadPoolExecutor p = 1353 new ThreadPoolExecutor(2, 3, 1354 LONG_DELAY_MS, MILLISECONDS, 1355 new ArrayBlockingQueue<Runnable>(10)); 1356 try { 1357 p.setMaximumPoolSize(-1); 1358 shouldThrow(); 1359 } catch (IllegalArgumentException success) { 1360 } finally { 1361 try { p.shutdown(); } catch (SecurityException ok) { return; } 1362 } 1363 joinPool(p); 1364 } 1365 1366 /** 1367 * setKeepAliveTime throws IllegalArgumentException 1368 * when given a negative value 1369 */ 1370 public void testKeepAliveTimeIllegalArgumentException() { 1371 ThreadPoolExecutor p = 1372 new ThreadPoolExecutor(2, 3, 1373 LONG_DELAY_MS, MILLISECONDS, 1374 new ArrayBlockingQueue<Runnable>(10)); 1375 try { 1376 p.setKeepAliveTime(-1,MILLISECONDS); 1377 shouldThrow(); 1378 } catch (IllegalArgumentException success) { 1379 } finally { 1380 try { p.shutdown(); } catch (SecurityException ok) { return; } 1381 } 1382 joinPool(p); 1383 } 1384 1385 /** 1386 * terminated() is called on termination 1387 */ 1388 public void testTerminated() { 1389 ExtendedTPE p = new ExtendedTPE(); 1390 try { p.shutdown(); } catch (SecurityException ok) { return; } 1391 assertTrue(p.terminatedCalled()); 1392 joinPool(p); 1393 } 1394 1395 /** 1396 * beforeExecute and afterExecute are called when executing task 1397 */ 1398 public void testBeforeAfter() throws InterruptedException { 1399 ExtendedTPE p = new ExtendedTPE(); 1400 try { 1401 final CountDownLatch done = new CountDownLatch(1); 1402 p.execute(new CheckedRunnable() { 1403 public void realRun() { 1404 done.countDown(); 1405 }}); 1406 await(p.afterCalled); 1407 assertEquals(0, done.getCount()); 1408 assertTrue(p.afterCalled()); 1409 assertTrue(p.beforeCalled()); 1410 try { p.shutdown(); } catch (SecurityException ok) { return; } 1411 } finally { 1412 joinPool(p); 1413 } 1414 } 1415 1416 /** 1417 * completed submit of callable returns result 1418 */ 1419 public void testSubmitCallable() throws Exception { 1420 ExecutorService e = 1421 new ThreadPoolExecutor(2, 2, 1422 LONG_DELAY_MS, MILLISECONDS, 1423 new ArrayBlockingQueue<Runnable>(10)); 1424 try { 1425 Future<String> future = e.submit(new StringTask()); 1426 String result = future.get(); 1427 assertSame(TEST_STRING, result); 1428 } finally { 1429 joinPool(e); 1430 } 1431 } 1432 1433 /** 1434 * completed submit of runnable returns successfully 1435 */ 1436 public void testSubmitRunnable() throws Exception { 1437 ExecutorService e = 1438 new ThreadPoolExecutor(2, 2, 1439 LONG_DELAY_MS, MILLISECONDS, 1440 new ArrayBlockingQueue<Runnable>(10)); 1441 try { 1442 Future<?> future = e.submit(new NoOpRunnable()); 1443 future.get(); 1444 assertTrue(future.isDone()); 1445 } finally { 1446 joinPool(e); 1447 } 1448 } 1449 1450 /** 1451 * completed submit of (runnable, result) returns result 1452 */ 1453 public void testSubmitRunnable2() throws Exception { 1454 ExecutorService e = 1455 new ThreadPoolExecutor(2, 2, 1456 LONG_DELAY_MS, MILLISECONDS, 1457 new ArrayBlockingQueue<Runnable>(10)); 1458 try { 1459 Future<String> future = e.submit(new NoOpRunnable(), TEST_STRING); 1460 String result = future.get(); 1461 assertSame(TEST_STRING, result); 1462 } finally { 1463 joinPool(e); 1464 } 1465 } 1466 1467 /** 1468 * invokeAny(null) throws NPE 1469 */ 1470 public void testInvokeAny1() throws Exception { 1471 ExecutorService e = 1472 new ThreadPoolExecutor(2, 2, 1473 LONG_DELAY_MS, MILLISECONDS, 1474 new ArrayBlockingQueue<Runnable>(10)); 1475 try { 1476 e.invokeAny(null); 1477 shouldThrow(); 1478 } catch (NullPointerException success) { 1479 } finally { 1480 joinPool(e); 1481 } 1482 } 1483 1484 /** 1485 * invokeAny(empty collection) throws IAE 1486 */ 1487 public void testInvokeAny2() throws Exception { 1488 ExecutorService e = 1489 new ThreadPoolExecutor(2, 2, 1490 LONG_DELAY_MS, MILLISECONDS, 1491 new ArrayBlockingQueue<Runnable>(10)); 1492 try { 1493 e.invokeAny(new ArrayList<Callable<String>>()); 1494 shouldThrow(); 1495 } catch (IllegalArgumentException success) { 1496 } finally { 1497 joinPool(e); 1498 } 1499 } 1500 1501 /** 1502 * invokeAny(c) throws NPE if c has null elements 1503 */ 1504 public void testInvokeAny3() throws Exception { 1505 final CountDownLatch latch = new CountDownLatch(1); 1506 final ExecutorService e = 1507 new ThreadPoolExecutor(2, 2, 1508 LONG_DELAY_MS, MILLISECONDS, 1509 new ArrayBlockingQueue<Runnable>(10)); 1510 List<Callable<String>> l = new ArrayList<Callable<String>>(); 1511 l.add(latchAwaitingStringTask(latch)); 1512 l.add(null); 1513 try { 1514 e.invokeAny(l); 1515 shouldThrow(); 1516 } catch (NullPointerException success) { 1517 } finally { 1518 latch.countDown(); 1519 joinPool(e); 1520 } 1521 } 1522 1523 /** 1524 * invokeAny(c) throws ExecutionException if no task completes 1525 */ 1526 public void testInvokeAny4() throws Exception { 1527 ExecutorService e = 1528 new ThreadPoolExecutor(2, 2, 1529 LONG_DELAY_MS, MILLISECONDS, 1530 new ArrayBlockingQueue<Runnable>(10)); 1531 List<Callable<String>> l = new ArrayList<Callable<String>>(); 1532 l.add(new NPETask()); 1533 try { 1534 e.invokeAny(l); 1535 shouldThrow(); 1536 } catch (ExecutionException success) { 1537 assertTrue(success.getCause() instanceof NullPointerException); 1538 } finally { 1539 joinPool(e); 1540 } 1541 } 1542 1543 /** 1544 * invokeAny(c) returns result of some task 1545 */ 1546 public void testInvokeAny5() throws Exception { 1547 ExecutorService e = 1548 new ThreadPoolExecutor(2, 2, 1549 LONG_DELAY_MS, MILLISECONDS, 1550 new ArrayBlockingQueue<Runnable>(10)); 1551 try { 1552 List<Callable<String>> l = new ArrayList<Callable<String>>(); 1553 l.add(new StringTask()); 1554 l.add(new StringTask()); 1555 String result = e.invokeAny(l); 1556 assertSame(TEST_STRING, result); 1557 } finally { 1558 joinPool(e); 1559 } 1560 } 1561 1562 /** 1563 * invokeAll(null) throws NPE 1564 */ 1565 public void testInvokeAll1() throws Exception { 1566 ExecutorService e = 1567 new ThreadPoolExecutor(2, 2, 1568 LONG_DELAY_MS, MILLISECONDS, 1569 new ArrayBlockingQueue<Runnable>(10)); 1570 try { 1571 e.invokeAll(null); 1572 shouldThrow(); 1573 } catch (NullPointerException success) { 1574 } finally { 1575 joinPool(e); 1576 } 1577 } 1578 1579 /** 1580 * invokeAll(empty collection) returns empty collection 1581 */ 1582 public void testInvokeAll2() throws InterruptedException { 1583 ExecutorService e = 1584 new ThreadPoolExecutor(2, 2, 1585 LONG_DELAY_MS, MILLISECONDS, 1586 new ArrayBlockingQueue<Runnable>(10)); 1587 try { 1588 List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>()); 1589 assertTrue(r.isEmpty()); 1590 } finally { 1591 joinPool(e); 1592 } 1593 } 1594 1595 /** 1596 * invokeAll(c) throws NPE if c has null elements 1597 */ 1598 public void testInvokeAll3() throws Exception { 1599 ExecutorService e = 1600 new ThreadPoolExecutor(2, 2, 1601 LONG_DELAY_MS, MILLISECONDS, 1602 new ArrayBlockingQueue<Runnable>(10)); 1603 List<Callable<String>> l = new ArrayList<Callable<String>>(); 1604 l.add(new StringTask()); 1605 l.add(null); 1606 try { 1607 e.invokeAll(l); 1608 shouldThrow(); 1609 } catch (NullPointerException success) { 1610 } finally { 1611 joinPool(e); 1612 } 1613 } 1614 1615 /** 1616 * get of element of invokeAll(c) throws exception on failed task 1617 */ 1618 public void testInvokeAll4() throws Exception { 1619 ExecutorService e = 1620 new ThreadPoolExecutor(2, 2, 1621 LONG_DELAY_MS, MILLISECONDS, 1622 new ArrayBlockingQueue<Runnable>(10)); 1623 try { 1624 List<Callable<String>> l = new ArrayList<Callable<String>>(); 1625 l.add(new NPETask()); 1626 List<Future<String>> futures = e.invokeAll(l); 1627 assertEquals(1, futures.size()); 1628 try { 1629 futures.get(0).get(); 1630 shouldThrow(); 1631 } catch (ExecutionException success) { 1632 assertTrue(success.getCause() instanceof NullPointerException); 1633 } 1634 } finally { 1635 joinPool(e); 1636 } 1637 } 1638 1639 /** 1640 * invokeAll(c) returns results of all completed tasks 1641 */ 1642 public void testInvokeAll5() throws Exception { 1643 ExecutorService e = 1644 new ThreadPoolExecutor(2, 2, 1645 LONG_DELAY_MS, MILLISECONDS, 1646 new ArrayBlockingQueue<Runnable>(10)); 1647 try { 1648 List<Callable<String>> l = new ArrayList<Callable<String>>(); 1649 l.add(new StringTask()); 1650 l.add(new StringTask()); 1651 List<Future<String>> futures = e.invokeAll(l); 1652 assertEquals(2, futures.size()); 1653 for (Future<String> future : futures) 1654 assertSame(TEST_STRING, future.get()); 1655 } finally { 1656 joinPool(e); 1657 } 1658 } 1659 1660 /** 1661 * timed invokeAny(null) throws NPE 1662 */ 1663 public void testTimedInvokeAny1() throws Exception { 1664 ExecutorService e = 1665 new ThreadPoolExecutor(2, 2, 1666 LONG_DELAY_MS, MILLISECONDS, 1667 new ArrayBlockingQueue<Runnable>(10)); 1668 try { 1669 e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS); 1670 shouldThrow(); 1671 } catch (NullPointerException success) { 1672 } finally { 1673 joinPool(e); 1674 } 1675 } 1676 1677 /** 1678 * timed invokeAny(,,null) throws NPE 1679 */ 1680 public void testTimedInvokeAnyNullTimeUnit() throws Exception { 1681 ExecutorService e = 1682 new ThreadPoolExecutor(2, 2, 1683 LONG_DELAY_MS, MILLISECONDS, 1684 new ArrayBlockingQueue<Runnable>(10)); 1685 List<Callable<String>> l = new ArrayList<Callable<String>>(); 1686 l.add(new StringTask()); 1687 try { 1688 e.invokeAny(l, MEDIUM_DELAY_MS, null); 1689 shouldThrow(); 1690 } catch (NullPointerException success) { 1691 } finally { 1692 joinPool(e); 1693 } 1694 } 1695 1696 /** 1697 * timed invokeAny(empty collection) throws IAE 1698 */ 1699 public void testTimedInvokeAny2() throws Exception { 1700 ExecutorService e = 1701 new ThreadPoolExecutor(2, 2, 1702 LONG_DELAY_MS, MILLISECONDS, 1703 new ArrayBlockingQueue<Runnable>(10)); 1704 try { 1705 e.invokeAny(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS); 1706 shouldThrow(); 1707 } catch (IllegalArgumentException success) { 1708 } finally { 1709 joinPool(e); 1710 } 1711 } 1712 1713 /** 1714 * timed invokeAny(c) throws NPE if c has null elements 1715 */ 1716 public void testTimedInvokeAny3() throws Exception { 1717 final CountDownLatch latch = new CountDownLatch(1); 1718 final ExecutorService e = 1719 new ThreadPoolExecutor(2, 2, 1720 LONG_DELAY_MS, MILLISECONDS, 1721 new ArrayBlockingQueue<Runnable>(10)); 1722 List<Callable<String>> l = new ArrayList<Callable<String>>(); 1723 l.add(latchAwaitingStringTask(latch)); 1724 l.add(null); 1725 try { 1726 e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS); 1727 shouldThrow(); 1728 } catch (NullPointerException success) { 1729 } finally { 1730 latch.countDown(); 1731 joinPool(e); 1732 } 1733 } 1734 1735 /** 1736 * timed invokeAny(c) throws ExecutionException if no task completes 1737 */ 1738 public void testTimedInvokeAny4() throws Exception { 1739 ExecutorService e = 1740 new ThreadPoolExecutor(2, 2, 1741 LONG_DELAY_MS, MILLISECONDS, 1742 new ArrayBlockingQueue<Runnable>(10)); 1743 List<Callable<String>> l = new ArrayList<Callable<String>>(); 1744 l.add(new NPETask()); 1745 try { 1746 e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS); 1747 shouldThrow(); 1748 } catch (ExecutionException success) { 1749 assertTrue(success.getCause() instanceof NullPointerException); 1750 } finally { 1751 joinPool(e); 1752 } 1753 } 1754 1755 /** 1756 * timed invokeAny(c) returns result of some task 1757 */ 1758 public void testTimedInvokeAny5() throws Exception { 1759 ExecutorService e = 1760 new ThreadPoolExecutor(2, 2, 1761 LONG_DELAY_MS, MILLISECONDS, 1762 new ArrayBlockingQueue<Runnable>(10)); 1763 try { 1764 List<Callable<String>> l = new ArrayList<Callable<String>>(); 1765 l.add(new StringTask()); 1766 l.add(new StringTask()); 1767 String result = e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS); 1768 assertSame(TEST_STRING, result); 1769 } finally { 1770 joinPool(e); 1771 } 1772 } 1773 1774 /** 1775 * timed invokeAll(null) throws NPE 1776 */ 1777 public void testTimedInvokeAll1() throws Exception { 1778 ExecutorService e = 1779 new ThreadPoolExecutor(2, 2, 1780 LONG_DELAY_MS, MILLISECONDS, 1781 new ArrayBlockingQueue<Runnable>(10)); 1782 try { 1783 e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS); 1784 shouldThrow(); 1785 } catch (NullPointerException success) { 1786 } finally { 1787 joinPool(e); 1788 } 1789 } 1790 1791 /** 1792 * timed invokeAll(,,null) throws NPE 1793 */ 1794 public void testTimedInvokeAllNullTimeUnit() throws Exception { 1795 ExecutorService e = 1796 new ThreadPoolExecutor(2, 2, 1797 LONG_DELAY_MS, MILLISECONDS, 1798 new ArrayBlockingQueue<Runnable>(10)); 1799 List<Callable<String>> l = new ArrayList<Callable<String>>(); 1800 l.add(new StringTask()); 1801 try { 1802 e.invokeAll(l, MEDIUM_DELAY_MS, null); 1803 shouldThrow(); 1804 } catch (NullPointerException success) { 1805 } finally { 1806 joinPool(e); 1807 } 1808 } 1809 1810 /** 1811 * timed invokeAll(empty collection) returns empty collection 1812 */ 1813 public void testTimedInvokeAll2() throws InterruptedException { 1814 ExecutorService e = 1815 new ThreadPoolExecutor(2, 2, 1816 LONG_DELAY_MS, MILLISECONDS, 1817 new ArrayBlockingQueue<Runnable>(10)); 1818 try { 1819 List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS); 1820 assertTrue(r.isEmpty()); 1821 } finally { 1822 joinPool(e); 1823 } 1824 } 1825 1826 /** 1827 * timed invokeAll(c) throws NPE if c has null elements 1828 */ 1829 public void testTimedInvokeAll3() throws Exception { 1830 ExecutorService e = 1831 new ThreadPoolExecutor(2, 2, 1832 LONG_DELAY_MS, MILLISECONDS, 1833 new ArrayBlockingQueue<Runnable>(10)); 1834 List<Callable<String>> l = new ArrayList<Callable<String>>(); 1835 l.add(new StringTask()); 1836 l.add(null); 1837 try { 1838 e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS); 1839 shouldThrow(); 1840 } catch (NullPointerException success) { 1841 } finally { 1842 joinPool(e); 1843 } 1844 } 1845 1846 /** 1847 * get of element of invokeAll(c) throws exception on failed task 1848 */ 1849 public void testTimedInvokeAll4() throws Exception { 1850 ExecutorService e = 1851 new ThreadPoolExecutor(2, 2, 1852 LONG_DELAY_MS, MILLISECONDS, 1853 new ArrayBlockingQueue<Runnable>(10)); 1854 List<Callable<String>> l = new ArrayList<Callable<String>>(); 1855 l.add(new NPETask()); 1856 List<Future<String>> futures = 1857 e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS); 1858 assertEquals(1, futures.size()); 1859 try { 1860 futures.get(0).get(); 1861 shouldThrow(); 1862 } catch (ExecutionException success) { 1863 assertTrue(success.getCause() instanceof NullPointerException); 1864 } finally { 1865 joinPool(e); 1866 } 1867 } 1868 1869 /** 1870 * timed invokeAll(c) returns results of all completed tasks 1871 */ 1872 public void testTimedInvokeAll5() throws Exception { 1873 ExecutorService e = 1874 new ThreadPoolExecutor(2, 2, 1875 LONG_DELAY_MS, MILLISECONDS, 1876 new ArrayBlockingQueue<Runnable>(10)); 1877 try { 1878 List<Callable<String>> l = new ArrayList<Callable<String>>(); 1879 l.add(new StringTask()); 1880 l.add(new StringTask()); 1881 List<Future<String>> futures = 1882 e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS); 1883 assertEquals(2, futures.size()); 1884 for (Future<String> future : futures) 1885 assertSame(TEST_STRING, future.get()); 1886 } finally { 1887 joinPool(e); 1888 } 1889 } 1890 1891 /** 1892 * timed invokeAll(c) cancels tasks not completed by timeout 1893 */ 1894 public void testTimedInvokeAll6() throws Exception { 1895 ExecutorService e = 1896 new ThreadPoolExecutor(2, 2, 1897 LONG_DELAY_MS, MILLISECONDS, 1898 new ArrayBlockingQueue<Runnable>(10)); 1899 try { 1900 List<Callable<String>> l = new ArrayList<Callable<String>>(); 1901 l.add(new StringTask()); 1902 l.add(Executors.callable(new MediumPossiblyInterruptedRunnable(), TEST_STRING)); 1903 l.add(new StringTask()); 1904 List<Future<String>> futures = 1905 e.invokeAll(l, SHORT_DELAY_MS, MILLISECONDS); 1906 assertEquals(l.size(), futures.size()); 1907 for (Future future : futures) 1908 assertTrue(future.isDone()); 1909 assertFalse(futures.get(0).isCancelled()); 1910 assertTrue(futures.get(1).isCancelled()); 1911 } finally { 1912 joinPool(e); 1913 } 1914 } 1915 1916 /** 1917 * Execution continues if there is at least one thread even if 1918 * thread factory fails to create more 1919 */ 1920 public void testFailingThreadFactory() throws InterruptedException { 1921 final ExecutorService e = 1922 new ThreadPoolExecutor(100, 100, 1923 LONG_DELAY_MS, MILLISECONDS, 1924 new LinkedBlockingQueue<Runnable>(), 1925 new FailingThreadFactory()); 1926 try { 1927 final int TASKS = 100; 1928 final CountDownLatch done = new CountDownLatch(TASKS); 1929 for (int k = 0; k < TASKS; ++k) 1930 e.execute(new CheckedRunnable() { 1931 public void realRun() { 1932 done.countDown(); 1933 }}); 1934 assertTrue(done.await(LONG_DELAY_MS, MILLISECONDS)); 1935 } finally { 1936 joinPool(e); 1937 } 1938 } 1939 1940 /** 1941 * allowsCoreThreadTimeOut is by default false. 1942 */ 1943 public void testAllowsCoreThreadTimeOut() { 1944 final ThreadPoolExecutor p = 1945 new ThreadPoolExecutor(2, 2, 1946 1000, MILLISECONDS, 1947 new ArrayBlockingQueue<Runnable>(10)); 1948 assertFalse(p.allowsCoreThreadTimeOut()); 1949 joinPool(p); 1950 } 1951 1952 /** 1953 * allowCoreThreadTimeOut(true) causes idle threads to time out 1954 */ 1955 public void testAllowCoreThreadTimeOut_true() throws Exception { 1956 long coreThreadTimeOut = SHORT_DELAY_MS; 1957 final ThreadPoolExecutor p = 1958 new ThreadPoolExecutor(2, 10, 1959 coreThreadTimeOut, MILLISECONDS, 1960 new ArrayBlockingQueue<Runnable>(10)); 1961 final CountDownLatch threadStarted = new CountDownLatch(1); 1962 try { 1963 p.allowCoreThreadTimeOut(true); 1964 p.execute(new CheckedRunnable() { 1965 public void realRun() { 1966 threadStarted.countDown(); 1967 assertEquals(1, p.getPoolSize()); 1968 }}); 1969 await(threadStarted); 1970 delay(coreThreadTimeOut); 1971 long startTime = System.nanoTime(); 1972 while (p.getPoolSize() > 0 1973 && millisElapsedSince(startTime) < LONG_DELAY_MS) 1974 Thread.yield(); 1975 assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); 1976 assertEquals(0, p.getPoolSize()); 1977 } finally { 1978 joinPool(p); 1979 } 1980 } 1981 1982 /** 1983 * allowCoreThreadTimeOut(false) causes idle threads not to time out 1984 */ 1985 public void testAllowCoreThreadTimeOut_false() throws Exception { 1986 long coreThreadTimeOut = SHORT_DELAY_MS; 1987 final ThreadPoolExecutor p = 1988 new ThreadPoolExecutor(2, 10, 1989 coreThreadTimeOut, MILLISECONDS, 1990 new ArrayBlockingQueue<Runnable>(10)); 1991 final CountDownLatch threadStarted = new CountDownLatch(1); 1992 try { 1993 p.allowCoreThreadTimeOut(false); 1994 p.execute(new CheckedRunnable() { 1995 public void realRun() throws InterruptedException { 1996 threadStarted.countDown(); 1997 assertTrue(p.getPoolSize() >= 1); 1998 }}); 1999 delay(2 * coreThreadTimeOut); 2000 assertTrue(p.getPoolSize() >= 1); 2001 } finally { 2002 joinPool(p); 2003 } 2004 } 2005 2006 /** 2007 * execute allows the same task to be submitted multiple times, even 2008 * if rejected 2009 */ 2010 public void testRejectedRecycledTask() throws InterruptedException { 2011 final int nTasks = 1000; 2012 final CountDownLatch done = new CountDownLatch(nTasks); 2013 final Runnable recycledTask = new Runnable() { 2014 public void run() { 2015 done.countDown(); 2016 }}; 2017 final ThreadPoolExecutor p = 2018 new ThreadPoolExecutor(1, 30, 60, TimeUnit.SECONDS, 2019 new ArrayBlockingQueue(30)); 2020 try { 2021 for (int i = 0; i < nTasks; ++i) { 2022 for (;;) { 2023 try { 2024 p.execute(recycledTask); 2025 break; 2026 } 2027 catch (RejectedExecutionException ignore) {} 2028 } 2029 } 2030 // enough time to run all tasks 2031 assertTrue(done.await(nTasks * SHORT_DELAY_MS, MILLISECONDS)); 2032 } finally { 2033 joinPool(p); 2034 } 2035 } 2036 2037 } 2038