ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ThreadPoolExecutor.java
(Generate patch)

Comparing jsr166/src/main/java/util/concurrent/ThreadPoolExecutor.java (file contents):
Revision 1.112 by jsr166, Mon Sep 4 08:00:47 2006 UTC vs.
Revision 1.113 by jsr166, Thu Sep 7 20:01:04 2006 UTC

# Line 563 | Line 563 | public class ThreadPoolExecutor extends
563                  (rs == SHUTDOWN && !workQueue.isEmpty()))
564                  return;
565              if (workerCountOf(c) != 0) { // Eligible to terminate
566 <                interruptIdleWorkers(true);
566 >                interruptIdleWorkers(ONLY_ONE);
567                  return;
568              }
569              if (ctl.compareAndSet(c, ctlOf(TERMINATED, 0))) {
# Line 651 | Line 651 | public class ThreadPoolExecutor extends
651       * called only from tryTerminate when termination is otherwise
652       * enabled but there are still other workers.  In this case, at
653       * most one waiting worker is interrupted to propagate shutdown
654 <     * signals in case all threads are currently waiting. This
655 <     * suffices because all waiting workers existing at point of a
656 <     * shutdown() call must have already been interrupted.
654 >     * signals in case all threads are currently waiting.
655       * Interrupting any arbitrary thread ensures that newly arriving
656       * workers since shutdown began will also eventually exit.
657 +     * To guarantee eventual termination, it suffices to always
658 +     * interrupt only one idle worker, but shutdown() interrupts all
659 +     * idle workers so that redundant workers exit promptly, not
660 +     * waiting for a straggler task to finish.
661       */
662      private void interruptIdleWorkers(boolean onlyOne) {
663          final ReentrantLock mainLock = this.mainLock;
# Line 681 | Line 683 | public class ThreadPoolExecutor extends
683          }
684      }
685  
686 +    private void interruptIdleWorkers() { interruptIdleWorkers(false); }
687 +    private static final boolean ONLY_ONE = true;
688 +
689      /**
690       * Ensures that unless the pool is stopping, the current thread
691       * does not have its interrupt set. This requires a double-check
# Line 777 | Line 782 | public class ThreadPoolExecutor extends
782          for (;;) {
783              int c = ctl.get();
784              int rs = runStateOf(c);
785 <            // Check if queue empty only if necessary, and re-read ctl
781 <            // after this call to make CAS more likely to succeed.
785 >            // Check if queue empty only if necessary.
786              if (rs == SHUTDOWN) {
787                  if (workQueue.isEmpty())
788                      return false;
789 <                if (runStateOf(c = ctl.get()) != rs)
790 <                    continue;
789 >                // isEmpty() may be slow, so re-read ctl to reduce the risk
790 >                // of CAS failing due to harmless change to workerCount.
791 >                c = ctl.get();
792              }
793              int wc = workerCountOf(c);
794              if (rs > SHUTDOWN ||
# Line 1214 | Line 1219 | public class ThreadPoolExecutor extends
1219          try {
1220              checkShutdownAccess();
1221              advanceRunState(SHUTDOWN);
1222 <            interruptIdleWorkers(false);
1222 >            interruptIdleWorkers();
1223              onShutdown(); // hook for ScheduledThreadPoolExecutor
1224          } finally {
1225              mainLock.unlock();
# Line 1369 | Line 1374 | public class ThreadPoolExecutor extends
1374          int delta = corePoolSize - this.corePoolSize;
1375          this.corePoolSize = corePoolSize;
1376          if (workerCountOf(ctl.get()) > corePoolSize)
1377 <            interruptIdleWorkers(false);
1377 >            interruptIdleWorkers();
1378          else if (delta > 0) {
1379              // We don't really know how many new threads are "needed".
1380              // As a heuristic, prestart enough new workers (up to new
# Line 1456 | Line 1461 | public class ThreadPoolExecutor extends
1461          if (value != allowCoreThreadTimeOut) {
1462              allowCoreThreadTimeOut = value;
1463              if (value)
1464 <                interruptIdleWorkers(false);
1464 >                interruptIdleWorkers();
1465          }
1466      }
1467  
# Line 1477 | Line 1482 | public class ThreadPoolExecutor extends
1482              throw new IllegalArgumentException();
1483          this.maximumPoolSize = maximumPoolSize;
1484          if (workerCountOf(ctl.get()) > maximumPoolSize)
1485 <            interruptIdleWorkers(false);
1485 >            interruptIdleWorkers();
1486      }
1487  
1488      /**
# Line 1512 | Line 1517 | public class ThreadPoolExecutor extends
1517          long delta = keepAliveTime - this.keepAliveTime;
1518          this.keepAliveTime = keepAliveTime;
1519          if (delta < 0)
1520 <            interruptIdleWorkers(false);
1520 >            interruptIdleWorkers();
1521      }
1522  
1523      /**

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines