United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6756747 java.util.concurrent.ThreadPoolExecutor doesn't create new worker when it should
JDK-6756747 : java.util.concurrent.ThreadPoolExecutor doesn't create new worker when it should

Details
Type:
Bug
Submit Date:
2008-10-07
Status:
Closed
Updated Date:
2011-02-16
Project Name:
JDK
Resolved Date:
2008-10-07
Component:
core-libs
OS:
windows_xp
Sub-Component:
java.util.concurrent
CPU:
x86
Priority:
P4
Resolution:
Not an Issue
Affected Versions:
6
Fixed Versions:

Related Reports

Sub Tasks

Description
FULL PRODUCT VERSION :
1.6.0_07-b06
1.6.0_10-rc2-b32

ADDITIONAL OS VERSION INFORMATION :
tested on WinXP SP2 (5.1.2600) and Ubuntu Linux 2.6.24-19-generic

A DESCRIPTION OF THE PROBLEM :
As can be seen with example listed below, ThreadPoolExecutor with corePoolSize value lower than maxPoolSize will never try to add new threads beyond corePoolSize when tasks are submitted using unbounded queue.



STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
execute supplied snippet and examine output.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
new thread should be created if task is submitted and current poolSize is lower than maxPoolSize.
ACTUAL -
all tasks are executed by the same thread one-by-one.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.util.concurrent.*;
import java.util.Collection;
import java.util.ArrayList;

public class Main {
    private static final int TASK_COUNT = 10;
    public static void main(String[] args) {
        final ThreadPoolExecutor tpe = new ThreadPoolExecutor(1, 5, 14, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(),new RejectedExecutionHandler()
        {
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                System.out.println(r + " execution rejected");
            }
        });
        final Collection<Task> tasks = new ArrayList<Task>();
        for (int i = 0; i < TASK_COUNT; i++) {
            tasks.add(new Task());
        }
        for (final Task task : tasks) {
					synchronized(tpe) {
            System.out.println(Thread.currentThread().getName() + " submitted task");
            System.out.println("poolsize = " + tpe.getPoolSize() + "; tasksCount = " + tpe.getTaskCount() );
            tpe.execute(task);
					}
        }

    }
}

class Task implements Runnable {
    public void run() {
        System.out.println(this +  " is being executed in " + Thread.currentThread().getName() + ": " + Thread.currentThread().hashCode());
        System.out.println(Thread.getAllStackTraces().size());
        try {
            Thread.sleep(500);
            System.out.println(this + " done executing in " + Thread.currentThread().getName() + ": " + Thread.currentThread().hashCode());
        } catch (InterruptedException e) {
            System.exit(-1);
            e.printStackTrace();
        }
    }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
always create ThreadPoolExecutor with corePoolSize equal to maxPoolSize

                                    

Comments
EVALUATION

> ThreadPoolExecutor with corePoolSize value lower than maxPoolSize will never try to
> add new threads beyond corePoolSize when tasks are submitted using unbounded queue.

And that is exactly how it is supposed to behave. First the threads grow to coreSize, then the queue is used, then *if* the queue fills up then the number of threads expands from coreSize to maxSize. Hence if you use an unbounded queue the last part never happens. This is all described in the documentation.

If you want an unbounded queue but more threads then increase the core size. Otherwise consider whether a bounded queue is more suitable to your needs.
                                     
2008-10-07



Hardware and Software, Engineered to Work Together