2011-12-28 7 views
7

에서 중단 된 후에도 계속 실행 8.스레드 어플은 봄과 <code>org.springframework.scheduling.commonj.WorkManagerTaskExecutor</code> 를 사용하여 생성되며, 웹 스피어 애플리케이션 서버에서 실행되는 장기 실행 스레드를 가지고 스피어

문제는이 스레드도 실행 유지한다는 것입니다 응용 프로그램이 중지 된 경우 그 실은 멈춰야 만하지만 그것은 일어나지 않습니다. 심지어는 Thread.currentThread().isInterrupted()을 사용하여 현재 스레드가 인터럽트되었는지를 확인하려고 시도했지만 항상 false을 반환합니다. 스레드가 계속 실행되거나 중지되어야 하는지를 코드를 통해 알 수있는 방법이 없습니다.

이것은 WorkManagerTaskExecutor 내 스프링 구성입니다 :

스레드가 이런 식으로 실행되고
<bean id="taskExecutor" class="org.springframework.scheduling.commonj.WorkManagerTaskExecutor"> 
     <property name="workManagerName" value="wm/default" /> 
</bean> 

:

Thread t = new EmailReaderThread(email); 
workManagerTaskExecutor.execute(t); 
  • 내가 무엇을 놓치고를?
  • 응용 프로그램이 중지 될 때마다 응용 프로그램의 스레드 (응용 프로그램에서 생성 된 스레드)도 중지되도록하려면 어떻게해야합니까?

컨테이너가 JNDI에 의해 리소스로 노출하는 적절한 WorkManager을 사용하여 스레드를 등록 중이므로 관리되지 않는 스레드로 간주되지 않습니다.

업데이트 : 다음은 스레드를 생성하는 코드입니다.

@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

스레드 대신 Runnable을 WorkManagerTaskExecutor.execute (WorkManagerTaskExecutor 작업)에 전달하면 안됩니까? – Hyangelo

+0

스레드는 Runnable을 구현하므로 Runnable입니다. 나는 그것이 문제가 아니라고 생각한다. –

+0

실행자는 전달 된 쓰레드의'start()'메소드를 결코 호출하지 않습니다 ('run()'만). 따라서 일반 실행 파일 (쓰레드가 아닌)을 사용할 수도 있습니다. –

답변

6

는 CommonJ 사양에 따르면, WorkManager는 isDaemon() 메소드가 true를 돌려주는 경우에만 작업 실행을 중지하려고 시도합니다. 비 데몬 (Non daemon) 작업은 중지 될 필요가 없도록 짧은 실행이 예상됩니다.

기본적으로 문제는 Spring에서 사용하는 Work 구현의 isDaemon() 메서드가 실제로는 Runnable을 래핑하고 false가 반환된다는 것입니다. Runnable이 SchedulingAwareRunnable을 구현하도록함으로써이를 변경할 수 있습니다.

그러나 충분하지 않습니다. WorkManager가 작업을 중단하기로 결정하면 Work # release()를 호출하고 작업 자체가 중지되는지 확인해야합니다. 특히, WorkManager는 작업을 실행중인 스레드를 인터럽트하지 않습니다 (스레드를 안정적으로 중지 할 수 없으므로). 문제는 Spring에서 사용하는 Work 구현이 release() 메소드에 대한 빈 구현을 가지고 있으므로 해당 기능을 사용할 수 없다는 점이다.

요약 : Spring을 사용하려면 실행을 중지하는 유일한 방법은이를위한 자체 메커니즘을 디자인하는 것입니다.

SchedulingAwareRunnable을 사용하면 여전히 흥미 롭습니다. WebSphere의 스레드 모니터 (스레드 매달기)에서 생성 된 경고를 피할 수 있기 때문입니다.

+0

WorkManagerTaskExecutor의 소스 코드를 확인했는데 작성한 내용이 완벽합니다. 고맙습니다. 자신의 구현으로 "release()"를 재정의 할 수 없다는 것은 매우 나쁘다고 생각합니다. –