-
Bug
-
Resolution: Duplicate
-
P3
-
None
-
7
-
sparc
-
solaris_10
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 ----------
$ 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 ----------
- duplicates
-
JDK-6576792 ThreadPoolExecutor methods leak interrupts when run in pool threads
-
- Resolved
-