Spring ThreadPoolTaskExecutor only running one thread
We are using ThreadPoolExecutor in our JMS consumer and injecting it into a DefaultMessageListenerContainer. I expect this to be running concurrent threads for many messages however our logs show that the thread id won't change.Our logging shows that for different processing of messages, the thread id is always the same at 24.
This is the spring configuration in that scenario:
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer"
p:connectionFact开发者_开发技巧ory-ref="cachedConnectionFactory"
p:destination-ref="formsCRRDestination"
p:messageListener-ref="formServicePojo"
p:concurrentConsumers="5"
p:idleTaskExecutionLimit="1"
p:maxConcurrentConsumers="25"
p:taskExecutor-ref="threadPoolExecutor"
destroy-method="doShutdown"
>
<bean id="threadPoolExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor" >
<property name="corePoolSize" value="1"/>
<property name="maxPoolSize" value="15"/>
<property name="keepAliveSeconds" value="30"/>
</bean>
After not injecting the threadPoolExectuor bean into the DefaultMessageListenerContainer, the messages are now being executed in different threads.
This is the resulting configuration:
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer"
p:connectionFactory-ref="cachedConnectionFactory"
p:destination-ref="formsCRRDestination"
p:messageListener-ref="formServicePojo"
p:concurrentConsumers="5"
p:idleTaskExecutionLimit="1"
p:maxConcurrentConsumers="25"
destroy-method="doShutdown"
>
I have tried reading the documentation and I don't understand why this is happening. Any explanation?
try this:
<bean id="threadPoolTaskExecutor"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="10" />
<property name="maxPoolSize" value="25" />
<property name="queueCapacity" value="30" />
</bean>
- This will create 10 threads at the time of initialization.
- If all 10 threads are busy and new task comes up, then It will keep tasks in queue.
- If queue is full it will create 11th thread and will go till 25.
- Then will throw TaskRejected Exception.
I think chosen answer is wrong. IIRC, the way ThreadPoolTaskExecutor (eventually ThreadPoolExecutor in JDK ) working is
- ThreadPoolTaskExecutor create threads to up corePoolSize when it's initiated.
- It takes request up to corePoolSize and let thread to process the task.
- If there are more requests incoming while all threads are busy, ThreadPoolTaskExecutor is start queuing up those request into internal queue. This can be problematic since this queue size will be Integer.MAX_VALUE as default if you don't specify queue queueCapacity.
- Request added in #3 will be executed by thread when there is any available threads in the pool.
- If requests are keep coming and all threads are busy & queue is full, the ThreadPoolTaskExecutor starts creating new threads up to maxPoolSize to process requests.
- If requests over those (increased threads number + queue size), then task will be rejected or following policy you specified.
So the problem here I think is, either 1) your consumer is fast enough or 2) you are stacking requests too slowly, so one thread you specify with corePoolSize was enough to process new incoming requests + queued task without allowing ThreadPoolTaskExecutor to create new threads. I'm pretty sure if you push it harder or set queue's capacity with small number ( like 5~10 ), you'll be able to see the number of threads is increasing.
After going through the ThreadPoolTaskExecutor code in Spring and reading the Java docs for ThreadPoolTaskExecutor I think this is the answer:
Unbounded queues. Using an unbounded queue (for example a LinkedBlockingQueue without a predefined capacity) will cause new tasks to be queued in cases where all corePoolSize threads are busy. Thus, no more than corePoolSize threads will ever be created. (And the value of the maximumPoolSize therefore doesn't have any effect.)
In our configuration above, we were using the LinkedBlockingQueue by default and our corePoolSize is 1. This is why the maximumPoolSize won't have any effect.
change the corePoolSize to 10, then you will get 10 threads run concurrently. Read the javadoc on java.util.concurrent.ThreadPoolExecutor which is the backbone of the spring ThreadPoolTaskExecutor, then you will have better understand how to config the corePoolSize and maxPoolSize and queueCapacity
精彩评论