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>; Date: Tue, Oct 26, 2021 03:08 PM To: "users"<users@tomcat.apache.org>; Subject: Re: About the comment of org.apache.tomcat.util.threads.TaskQueue On 26/10/2021 02:45, Poison wrote: > Thank you, I know the role of TaskQueue, but the comment about "normal queue" on the TaskQueue class is still incomprehensible. > > > 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. From the Javadoc of j.u.c.ThreadPoolExecutor: <quote> * When a new task is submitted in method {@link #execute(Runnable)}, * if fewer than corePoolSize threads are running, a new thread is * created to handle the request, even if other worker threads are * idle. Else if fewer than maximumPoolSize threads are running, a * new thread will be created to handle the request only if the queue * is full. By setting corePoolSize and maximumPoolSize the same, you * create a fixed-size thread pool. By setting maximumPoolSize to an * essentially unbounded value such as {@code Integer.MAX_VALUE}, you * allow the pool to accommodate an arbitrary number of concurrent * tasks. Most typically, core and maximum pool sizes are set only * upon construction, but they may also be changed dynamically using * {@link #setCorePoolSize} and {@link #setMaximumPoolSize}. </quote> 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