Spring ThreadPoolTaskExecutor只运行一个线程
我们在我们的JMS使用者中使用ThreadPoolExecutor并将它注入到DefaultMessageListenerContainer中。我期望这是为许多消息运行并发线程,但是我们的日志显示线程ID不会改变。我们的日志记录显示,对于不同的消息处理,线程ID在24处始终相同。Spring ThreadPoolTaskExecutor只运行一个线程
这是在该方案中的弹簧配置:
<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"
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>
不注入threadPoolExectuor豆成使用DefaultMessageListenerContainer后,消息现在被在不同的线程中执行。
这是生成的配置:
<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"
>
我曾尝试阅读文档,我不明白为什么会这样。任何解释?
通过ThreadPoolTaskExecutor code in Spring去和阅读Java文档为ThreadPoolTaskExecutor后,我觉得这就是答案:
无界队列。使用无限制的队列(例如 LinkedBlockingQueue不带 预定义容量)将导致新的 任务在所有 corePoolSize线程繁忙的情况下排队。因此, 不会超过corePoolSize线程 永远被创建。 (和 maximumPoolSize的值,因此不具有 任何影响。)
在我们的配置上面,我们正在使用的LinkedBlockingQueue默认情况下,我们的corePoolSize为1。这就是为什么maximumPoolSize不会有什么影响。
考虑编辑您的答案以添加有关如何解决问题的信息。什么java代码或弹簧配置应该改变?谢谢。 – Gray 2017-02-23 16:44:10
将corePoolSize更改为10,那么您将获得10个线程同时运行。 阅读java.util.concurrent.ThreadPoolExecutor中这是春天ThreadPoolTaskExecutor类的骨干javadoc,那么你将有更好地了解如何配置的corePoolSize和maxPoolSize和queueCapacity
我想选择的答案是错误的。 IIRC,顺便ThreadPoolTaskExecutor(最终的ThreadPoolExecutor在JDK)工作是
- ThreadPoolTaskExecutor类创建线程最多corePoolSize时,它的启动。
- 它将请求提交至corePoolSize并让线程处理任务。
- 如果在所有线程都忙时有更多请求传入,ThreadPoolTaskExecutor会将这些请求排入内部队列。这可能会有问题,因为如果不指定队列queueCapacity,则此队列大小将为Integer.MAX_VALUE作为默认值。
- 在#3中添加的请求将在线程池中存在任何可用线程时由线程执行。
- 如果请求继续来临,并且所有线程都忙&队列已满,ThreadPoolTaskExecutor开始创建新线程,直到maxPoolSize处理请求。
- 如果对这些请求(增加的线程数+队列大小),那么任务将被拒绝或遵循您指定的策略。
所以在这里我想问题是,无论是1)你的消费者是不够快或2)你是堆叠请求太慢,所以你corePoolSize指定一个线程足以处理新传入的请求+排队任务,而不允许ThreadPoolTaskExecutor创建新线程。我敢肯定,如果你更加努力地推动它,或者将队列的容量设置为较小的数量(如5〜10),您将能够看到线程数量正在增加。
试试这个:
<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>
- 这将在初始化时创建10个线程。
- 如果所有10个线程都处于忙碌状态并且出现新任务,那么它会将任务保留在队列中。
- 如果队列已满,它将创建第11个线程并且将一直持续到25.
- 然后会抛出TaskRejected异常。
我没有进入jms,但是您是否尝试同时发送很多消息?我猜这里的机制是只根据需求启动一个新线程(即没有空闲线程和新消息)。 – 2010-11-24 17:21:53
是的,我确实尝试在同一时间发送很多消息,只有一些消息需要很长时间才能处理。 – Jeune 2010-11-24 17:24:25