2010-11-24 133 views
11

我們在我們的JMS使用者中使用ThreadPoolExecutor並將它注入到DefaultMessageListenerContainer中。我期望這是爲許多消息運行併發線程,但是我們的日誌顯示線程ID不會改變。我們的日誌記錄顯示,對於不同的消息處理,線程ID在24處始終相同。Spring ThreadPoolTask​​Executor只運行一個線程

這是在該方案中的彈簧配置:

<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"  
     > 

我曾嘗試閱讀文檔,我不明白爲什麼會這樣。任何解釋?

+0

我沒有進入jms,但是您是否嘗試同時發送很多消息?我猜這裏的機制是隻根據需求啓動一個新線程(即沒有空閒線程和新消息)。 – 2010-11-24 17:21:53

+0

是的,我確實嘗試在同一時間發送很多消息,只有一些消息需要很長時間才能處理。 – Jeune 2010-11-24 17:24:25

回答

14

通過ThreadPoolTaskExecutor code in Spring去和閱讀Java文檔爲ThreadPoolTaskExecutor後,我覺得這就是答案:

無界隊列。使用無限制的隊列(例如 LinkedBlockingQueue不帶 預定義容量)將導致新的 任務在所有 corePoolSize線程繁忙的情況下排隊。因此, 不會超過corePoolSize線程 永遠被創建。 (和 maximumPoolSize的值,因此不具有 任何影響。)

在我們的配置上面,我們正在使用的LinkedBlockingQueue默認情況下,我們的corePoolSize爲1。這就是爲什麼maximumPoolSize不會有什麼影響。

+1

考慮編輯您的答案以添加有關如何解決問題的信息。什麼java代碼或彈簧配置應該改變?謝謝。 – Gray 2017-02-23 16:44:10

2

將corePoolSize更改爲10,那麼您將獲得10個線程同時運行。 閱讀java.util.concurrent.ThreadPoolExecutor中這是春天ThreadPoolTask​​Executor類的骨幹javadoc,那麼你將有更好地瞭解如何配置的corePoolSize和maxPoolSize和queueCapacity

7

我想選擇的答案是錯誤的。 IIRC,順便ThreadPoolTaskExecutor(最終的ThreadPoolExecutor在JDK)工作是

  1. ThreadPoolTask​​Executor類創建線程最多corePoolSize時,它的啓動。
  2. 它將請求提交至corePoolSize並讓線程處理任務。
  3. 如果在所有線程都忙時有更多請求傳入,ThreadPoolTask​​Executor會將這些請求排入內部隊列。這可能會有問題,因爲如果不指定隊列queueCapacity,則此隊列大小將爲Integer.MAX_VALUE作爲默認值。
  4. 在#3中添加的請求將在線程池中存在任何可用線程時由線程執行。
  5. 如果請求繼續來臨,並且所有線程都忙&隊列已滿,ThreadPoolTask​​Executor開始創建新線程,直到maxPoolSize處理請求。
  6. 如果對這些請求(增加的線程數+隊列大小),那麼任務將被拒絕或遵循您指定的策略。

所以在這裏我想問題是,無論是1)你的消費者是不夠快或2)你是堆疊請求太慢,所以你corePoolSize指定一個線程足以處理新傳入的請求+排隊任務,而不允許ThreadPoolTask​​Executor創建新線程。我敢肯定,如果你更加努力地推動它,或者將隊列的容量設置爲較小的數量(如5〜10),您將能夠看到線程數量正在增加。

28

試試這個:

<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異常。
相關問題