Reputation: 617
newFixedThreadPool.setCorePoolSize() doesn't make use of the threads, creates new theads.
Explanation: I make a newFixedThreadPool for size 2 and if both the threads of this pool are busy I add two more threads to this pool using setCorePoolSize(). In this process it doesn't seem to reuse the threads or may be terminating some threads and creating new which I will explain with code.
public class IncreasePoolSize
{
static ExecutorService service = null;
public static void main(String[] args) throws JMSException, InterruptedException
{
int NoOfth = 2;
int noOfTimesToInc = 0;
System.out.println("Start");
service = Executors.newFixedThreadPool(NoOfth);
for (;;)
{
if ( ((ThreadPoolExecutor)service).getActiveCount() >= NoOfth )
{
if (noOfTimesToInc < 1)
{
System.out.println("Increased Threads-" + (noOfTimesToInc + 1) + " time(s)");
NoOfth += 2;
System.out.println("NoOfTh-" + NoOfth);
((ThreadPoolExecutor)service).setCorePoolSize(NoOfth);
System.out.println("Total no of theads after increasing-" + ((ThreadPoolExecutor)service).getCorePoolSize());
noOfTimesToInc++;
}
}
else if ( ((ThreadPoolExecutor)service).getActiveCount() <= NoOfth)
{
service.execute(new ConcreteThread());
}
}
}
}
class ConcreteThread implements Runnable
{
public void run()
{
try
{
System.out.println("Thread No-" + Thread.currentThread().getId());
Thread.sleep(5000);
System.out.println("Thread No-" + Thread.currentThread().getId() + " finished");
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
It is seen in the output once thread no 11 and 12 start working, I increase the number by two and so thread 13 and 14 start working, but after that, i always creates new thread instead of using thread 11 and 12 and reuses thread 13 and 14.
Start
Thread No-11
Thread No-12
Increased Threads-1 time(s)
NoOfTh-4
Total no of theads after increasing-4
Thread No-13
Thread No-14
Thread No-11 finished
Thread No-12 finished
Thread No-13 finished
Thread No-14 finished
Thread No-15
Thread No-16
Thread No-13
Thread No-14
Thread No-15 finished
Thread No-16 finished
Thread No-13 finished
Thread No-14 finished
Thread No-17
Thread No-18
Thread No-13
Thread No-14
Thread No-17 finished
Thread No-18 finished
Thread No-13 finished
Thread No-14 finished
Thread No-19
Thread No-20
Thread No-13
Thread No-14
Thread No-19 finished
Thread No-20 finished
Thread No-13 finished
Thread No-14 finished
Thread No-21
Thread No-22
Thread No-13
Thread No-14
Thread No-21 finished
Thread No-22 finished
Thread No-13 finished
Thread No-14 finished
Thread No-23
Thread No-24
Thread No-13
Thread No-14
Upvotes: 6
Views: 3077
Reputation: 328659
One issue with your code is that you set the core pool size but not the maximum pool size. A newFixedThreadPool
uses the same number of core and maximum pool size and you somewhat break that contract.
If you add:
service.setMaximumPoolSize(NoOfth);
after setting the core pool size, the same 4 threads will be reused as you expect.
Note: this is actually a reported bug
The constructor of ThreadPoolExecutor and setMaximumPoolSize
throw an IllegalArgumentException if corePoolSize > maximumPoolSize
, but setCorePoolSize
does not.
Upvotes: 6
Reputation: 4844
If we go and look at the actual code being run we can see what's going on. In a thread pool the work is done by Worker threads which run this method (taken from here)
final void runWorker(Worker w) {
Runnable task = w.firstTask;
w.firstTask = null;
boolean completedAbruptly = true;
try {
while (task != null || (task = getTask()) != null) {
w.lock();
clearInterruptsForTaskRun();
try {
beforeExecute(w.thread, task);
Throwable thrown = null;
try {
task.run();
} catch (RuntimeException x) {
thrown = x; throw x;
} catch (Error x) {
thrown = x; throw x;
} catch (Throwable x) {
thrown = x; throw new Error(x);
} finally {
afterExecute(task, thrown);
}
} finally {
task = null;
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly);
}
}
As you can see this will carry on running tasks while there are tasks to run. However, if a Worker runs out of tasks it will die and if more tasks are scheduled later a new Worker (thread) will be created.
Upvotes: 0
Reputation: 32959
According to the javadoc of Executors.newFixedThreadPool
:
Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue. At any point, at most nThreads threads will be active processing tasks
So, it is not necessarily creating new threads, it is just using different threads from a shared unbounded queue
.
What the fixed thread pool is giving you is not that it will always use the exact same thread objects, but that the number of active threads working tasks in that executor will NEVER exceed the limit of the pool.
Upvotes: 2