Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6689310

Backmerge of 6576792 ThreadPoolExecutor#setCorePoolSize interrupts client code

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P3 P3
    • None
    • 7
    • core-libs

      FULL PRODUCT VERSION :
      $ java -version
      java version "1.6.0_03"
      Java(TM) SE Runtime Environment (build 1.6.0_03-b05)
      Java HotSpot(TM) Server VM (build 1.6.0_03-b05, mixed mode)


      ADDITIONAL OS VERSION INFORMATION :
      any os

      $ uname -a
      SunOS t1000 5.10 Generic_127111-09 sun4v sparc SUNW,Sun-Fire-T1000

      A DESCRIPTION OF THE PROBLEM :
      Decrease of ThreadPoolExecutor core pool size interrupts running tasks. This is described in http://bugs.sun.com/view_bug.do?bug_id=6576792 as regression which is not correct. The regression is that with the fixes incorporated in JDK 7 build 08 this bug will occur ALWAYS, before the fix the bug only occured OFTEN. A test case to prove this is provided below.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Submit a task to a ThreadPoolExecutor instance and call "setCorePoolSize" in task code.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The task is NOT interrupted.
      ACTUAL -
      The task IS interrupted.

      REPRODUCIBILITY :
      This bug can be reproduced often.

      ---------- BEGIN SOURCE ----------
      import java.util.concurrent.atomic.AtomicBoolean;
      import java.util.concurrent.ThreadPoolExecutor;
      import java.util.concurrent.LinkedBlockingQueue;
      import java.util.concurrent.TimeUnit;
      import java.util.concurrent.ExecutionException;


      public class Test {


      public void test() throws InterruptedException, ExecutionException {
      // thread pool executor with 3 slots; will be decreased to 1 to provoke thread interruption
      final ThreadPoolExecutor executor = new ThreadPoolExecutor(
      3, 3, // it's important to use a value of 3 because ThreadPoolExecutor.setMaximumPoolSize() only _tries_ "oldMaxCore - newMaxCore" times
      50, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());

      // 1st task: block first executor slot with sleeping
      executor.submit(new Runnable() {
      public void run() {
      try {
      Thread.sleep(1000);
      } catch (InterruptedException e) {
      throw new RuntimeException(e);
      }
      }
      });

      Thread.sleep(100); // wait a while to ensure that first task is really started

      // 2nd task: set maximum pool size to 1; this will lead ThreadPoolExecutor interrupting this thread although it is not idle
      final AtomicBoolean interrupted = new AtomicBoolean(false);
      executor.submit(new Runnable() {
      public void run() {
      executor.setCorePoolSize(1);
      executor.setMaximumPoolSize(1); // ThreadPoolExecutor will try to interrupt 3-1=2 tasks
      interrupted.set(Thread.currentThread().isInterrupted());
      }
      }).get(); // submit and wait

      assert !interrupted.get() : "thread was interrupted, bug still exists!";
      }


      public static void main(final String[] args) {
      try {
      new Test().test();
      } catch (final Exception e) {
      e.printStackTrace();
      System.exit(1);
      }
      System.exit(0);
      }
      }
      ---------- END SOURCE ----------

            Unassigned Unassigned
            ndcosta Nelson Dcosta (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: