2010-11-24 14 views
11

Estamos utilizando ThreadPoolExecutor en nuestro consumidor JMS e inyectarlo en un DefaultMessageListenerContainer. Espero que esto se ejecute hilos concurrentes para muchos mensajes, pero nuestros registros muestran que la identificación del hilo no cambiará. Nuestro registro muestra que para el procesamiento diferente de mensajes, el ID del hilo es siempre el mismo en 24.primavera ThreadPoolTaskExecutor sólo se ejecuta un hilo

Esto es la configuración de resorte en ese escenario:

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

Después de no inyección de la haba threadPoolExectuor en el DefaultMessageListenerContainer, los mensajes están siendo ejecutado en diferentes hilos.

Esta es la configuración resultante:

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

he tratado de leer la documentación y no entiendo por qué ocurre esto. ¿Alguna explicación?

+0

No estoy de acuerdo con jms, pero ¿has intentado enviar muchos mensajes al mismo tiempo? Supongo que el mecanismo aquí es iniciar un nuevo hilo solo a pedido (es decir, no hay un hilo inactivo y viene un nuevo mensaje). –

+0

Sí, sí intenté enviar muchos mensajes al mismo tiempo, solo algunos mensajes tardan mucho tiempo en procesarse. – Jeune

Respuesta

14

Después de pasar por el ThreadPoolTaskExecutor code in Spring y lectura de la documentación de Java para ThreadPoolTaskExecutor Creo que esta es la respuesta:

colas no acotadas. El uso de un cola sin límites (por ejemplo, un LinkedBlockingQueue sin una capacidad predefinida ) hará que nuevos tareas que se ponen en cola en los casos en que todos los hilos corePoolSize están ocupados. Por lo tanto, no se crearán más hilos de corePoolSize . (Y el valor de la maximumPoolSize por lo tanto, no tiene ningún efecto .)

En nuestra configuración anterior, estábamos usando el LinkedBlockingQueue por defecto y nuestra corePoolSize es 1. Esta es la razón por la maximumPoolSize no lo hará tiene algún efecto.

+1

Considere editar su respuesta para agregar información sobre cómo solucionar el problema. ¿Qué código java o configuración de primavera deberían cambiarse? Gracias. – Gray

2

cambio del corePoolSize a 10, por lo que recibirá 10 hilos se ejecutan simultáneamente. Lea la javadoc en java.util.concurrent.ThreadPoolExecutor que es la columna vertebral de la ThreadPoolTaskExecutor primavera, entonces tendrá que entender mejor cómo config El corePoolSize y maxPoolSize y queueCapacity

7

creo respuesta elegida es erróneo. IIRC, la forma ThreadPoolTaskExecutor (ThreadPoolExecutor finalmente en el JDK) de trabajo es

  1. ThreadPoolTaskExecutor crear hilos de hasta corePoolSize cuando se inició.
  2. Se necesita hasta corePoolSize y dejar que thread procese la tarea.
  3. Si hay más solicitudes de entrada, mientras que todos los temas están ocupados, ThreadPoolTaskExecutor es empezar a hacer cola en los que la solicitud cola interna. Esto puede ser problemático ya que este tamaño de cola será Integer.MAX_VALUE como predeterminado si no especifica queueColea de cola.
  4. Solicitud añadido en el # 3 será ejecutado por el hilo cuando no hay ningún hilo disponibles en la piscina.
  5. Si las solicitudes se siguen llegando y todos los temas están ocupados & cola está llena, el ThreadPoolTaskExecutor comienza a crear nuevos temas hasta maxPoolSize para procesar las solicitudes.
  6. Si las solicitudes superan (número de subprocesos + tamaño de cola), se rechazará la tarea o se seguirá la política especificada.

Así que el problema aquí creo que es, ya sea 1) su consumidor es lo suficientemente rápido o 2) está apilando las solicitudes demasiado lento, por lo que un hilo que especifique con corePoolSize fue suficiente para procesar la nueva solicitudes entrantes + tarea en cola sin permitiendo a ThreadPoolTaskExecutor crear nuevos hilos. Estoy bastante seguro de que si lo presionas más o configuras la capacidad de la cola con un número pequeño (como 5 ~ 10), podrás ver que el número de subprocesos está aumentando.

28

probar esto:

<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> 
  • Esto creará 10 hilos en el momento de la inicialización.
  • Si los 10 hilos están ocupados y aparece una nueva tarea, se mantendrán las tareas en cola.
  • Si la cola está llena, creará el undécimo subproceso y se extenderá hasta 25.
  • A continuación, arrojará excepción de TaskRejected.
+1

El problema con esta respuesta es que no explica por qué está sucediendo. Es por eso que la otra respuesta obtiene la marca de verificación para mí. Por otra parte, sería bueno que la respuesta aceptada explicara cómo solucionarlo. – Gray

Cuestiones relacionadas