2011-12-28 21 views
7

Tengo un hilo de ejecución larga que se ha creado usando org.springframework.scheduling.commonj.WorkManagerTaskExecutor con la primavera y se está ejecutando en Websphere Application Server 8.hilo sigue funcionando incluso después de la aplicación se ha detenido en Websphere

El problema es que este hilo sigue funcionando incluso si la aplicación ha sido detenida Ese hilo debe detenerse también, pero no está sucediendo. Incluso traté de usar Thread.currentThread().isInterrupted() para verificar si el hilo actual fue interrumpido pero siempre devuelve false. Así que no hay forma de saber a través de mi código si el hilo debe seguir funcionando o detenerse.

Esta es mi configuración del resorte para el WorkManagerTaskExecutor:

<bean id="taskExecutor" class="org.springframework.scheduling.commonj.WorkManagerTaskExecutor"> 
     <property name="workManagerName" value="wm/default" /> 
</bean> 

El hilo se está ejecutando de esta manera:

Thread t = new EmailReaderThread(email); 
workManagerTaskExecutor.execute(t); 
  • ¿Qué me falta?
  • ¿Qué puedo hacer para que cada vez que se detiene la aplicación, la cadena de la aplicación (hilos generados por la aplicación) también se detenga?

creo que esto no se considera un hilo no administrado porque yo estoy registrando el hilo con la adecuada WorkManager cual el contenedor expone como un recurso por JNDI.

Actualización: Aquí está el código que crea el subproceso.

@Service 
@Transactional 
public class SmsServiceHypermedia implements SmsService { 

    @Autowired 
    private WorkManagerTaskExecutor workManagerTaskExecutor; 


    public SmsServiceHypermedia() { 
     createEmailReaderThread(); 
    } 

    private void createEmailReaderThread() { 
     log.debug("Generating Email Reader Threads..."); 
     Email email = getDefaultEmail(); //obtain the default Email object, not important for the problem. 
     EmailReaderThread r = new EmailReaderThread(email); 
     workManagerTaskExecutor.execute(r);  
    } 

    private class EmailReaderThread extends Thread { 

     private Email email; 
     private Session session; 

     public EmailReaderThread(Email email) { 
      this.email = email; 
     } 

     @Override 
     public void run() { 
      readEmails(); 
     } 

     public void readEmails() { 
      final long delay = 30 * 1000; //delay between message poll. 
      log.debug("Starting to read emails for email: " + email.getAddress()); 
      while(!Thread.currentThread().isInterrupted()) { 
       try { 
        log.debug("Current session: " + session); 
        Store store = session.getStore(); 
        log.debug("Connecting using session: " + session); 
        store.connect(); 
        Folder inbox = store.getFolder("INBOX"); 
        inbox.open(Folder.READ_WRITE); 

        javax.mail.Message[] messages = inbox.search(
          new FlagTerm(new Flags(Flags.Flag.SEEN), false)); 
        for (javax.mail.Message message : messages) { 
         //Do something with the message 
        } 
        inbox.close(true); 
        store.close(); 
        block(delay); 
       } catch (Exception e) { 
        throw new RuntimeException(e); 
       } 
      } 
     } 

     //I know this could be implemented by calling Thread.sleep() is just that I ran out of options so I also tried it this way. 
     private void block(long millis) { 
      final long endTime = System.currentTimeMillis() + millis; 
      log.debug("Blocking for this amount of time: " + millis + " ms"); 
      while (System.currentTimeMillis() < endTime) { 
      } 
      log.debug("End of blocking."); 
     } 
    } 
} 
+0

¿No debería estar pasando un Runnable a WorkManagerTaskExecutor.execute (tarea WorkManagerTaskExecutor) en lugar de un subproceso? – Hyangelo

+0

Un subproceso implementa Runnable así que es Runnable. Creo que ese no es el problema. –

+0

ejecutores nunca llaman al método 'start()' de un hilo pasado (solo el 'run()') por lo que también podría usar un runnable normal (no un hilo) –

Respuesta

6

De acuerdo con las especificaciones CommonJ, un WorkManager intentará detener la ejecución de un trabajo sólo si su método isDaemon() devuelve verdadero. Se espera que los trabajos no demoníacos funcionen a corto plazo para que no necesiten detenerse.

El problema es que, de forma predeterminada, el método isDaemon() de la implementación del trabajo utilizado por Spring (y que en realidad ajusta el Runnable) devuelve falso. Puede cambiar eso haciendo que Runnable implemente SchedulingAwareRunnable.

Sin embargo, eso no es suficiente. Si el WorkManager decide detener el trabajo, llamará a la publicación Work #() y es responsabilidad del propio trabajo asegurarse de que se detenga. En particular, el WorkManager no intentará interrumpir el hilo que está ejecutando el trabajo (porque esa no es una manera confiable de detener un hilo). El problema es que la implementación Work utilizada por Spring tiene una implementación vacía para el método release(), por lo que no puede usar esa característica.

En resumen: si desea utilizar Spring, la única forma de asegurarse de que la ejecución se detiene es diseñar su propio mecanismo para eso.

Tenga en cuenta que todavía es interesante utilizar SchedulingAwareRunnable, ya que esto evitará las advertencias generadas por el supervisor de hilos de WebSphere (acerca de colgar hilos).

+0

Comprobé el código fuente de WorkManagerTaskExecutor y lo que escribió tiene mucho sentido. Gracias. Creo que es muy malo que no puedas anular el "lanzamiento()" con tu propia implementación. –

Cuestiones relacionadas