Thank you for your detailed explanation. Now I understand the background of 
this part of the comment. When corePoolSize is equal to maxThreads, the native 
implementation will create threads first.


There is another question. Why does 
org.apache.tomcat.util.threads.ThreadPoolExecutor almost copy the code of 
java.util.concurrent.ThreadPoolExecutor instead of implementing it by 
inheriting java.util.concurrent.ThreadPoolExecutor? This is what I don't 
understand. Hope you can explain the design concept behind, thank you.




------------------ Original ------------------
From:                                                                           
                                             "Tomcat Users List"                
                                                                    
<ma...@apache.org&gt;;
Date:&nbsp;Tue, Oct 26, 2021 03:08 PM
To:&nbsp;"users"<users@tomcat.apache.org&gt;;

Subject:&nbsp;Re: About the comment of org.apache.tomcat.util.threads.TaskQueue



On 26/10/2021 02:45, Poison wrote:
&gt; Thank you, I know the role of TaskQueue, but the comment about "normal 
queue" on the TaskQueue class is still incomprehensible.
&gt; 
&gt; 
&gt; In the java.util.concurrent.ThreadPoolExecutor#execute method, the comment 
mentions: "3. If we cannot queue task, then we try to add a new thread. If it 
fails, we know we are shut down or saturated and so reject the task.". Explain 
that the JDK prioritizes putting tasks into the queue rather than creating 
threads first, which is not consistent with the statement that "normal queue" 
mentioned in TaskQueue prioritizes thread creation.

You need to look at the custom queue and custom ThreadPoolExecutor together.

&nbsp;From the Javadoc of j.u.c.ThreadPoolExecutor:

<quote&gt;
&nbsp; * When a new task is submitted in method {@link #execute(Runnable)},
&nbsp; * if fewer than corePoolSize threads are running, a new thread is
&nbsp; * created to handle the request, even if other worker threads are
&nbsp; * idle.&nbsp; Else if fewer than maximumPoolSize threads are running, a
&nbsp; * new thread will be created to handle the request only if the queue
&nbsp; * is full.&nbsp; By setting corePoolSize and maximumPoolSize the same, 
you
&nbsp; * create a fixed-size thread pool. By setting maximumPoolSize to an
&nbsp; * essentially unbounded value such as {@code Integer.MAX_VALUE}, you
&nbsp; * allow the pool to accommodate an arbitrary number of concurrent
&nbsp; * tasks. Most typically, core and maximum pool sizes are set only
&nbsp; * upon construction, but they may also be changed dynamically using
&nbsp; * {@link #setCorePoolSize} and {@link #setMaximumPoolSize}.
</quote&gt;

The problem is that the default behaviour prioritises in this way:
- start corePoolSize threads
- queue tasks
- start additional threads up to maximumPoolSize if the queue is full

That isn't the behaviour we want in Tomcat. In Tomcat we want:
- start corePoolSize threads
- start additional threads up to maximumPoolSize
- queue tasks using an (effectively) infinite queue

That change has significant implications. These are most obviously seen 
in Tomcat's TaskQueue.offer(Runnable) implementation.

The closest you can get to the required Tomcat behaviour with 
j.u.c.ThreadPoolExecutor is by setting corePoolSize to maxThreads. 
However, this has the side effect that threads will be created for each 
new task until maxThreads have been started - hence the comment that it 
prioritises thread creation rather than re-using idle threads. You 
essentially end up with a fixed size thread pool of maxThreads - rather 
than what we want which (by default) is a thread pool of at least 
minSpareThreads that grows, if necessary, up to maxThreads and then 
shrinks back down to minSpareThreads while idle.

Mark

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to