2011-12-28 9 views
7

में रोक दिया गया है मैं एक लंबे धागे चल रहे हों जो वसंत के साथ org.springframework.scheduling.commonj.WorkManagerTaskExecutor का उपयोग कर बनाया जाता है और WebSphere अनुप्रयोग सर्वर में चल रहा है है चल रहता है 8.थ्रेड के बाद भी आवेदन Websphere

समस्या यह है कि इस सूत्र भी चलता रहे है अगर आवेदन बंद कर दिया गया है। उस थ्रेड को भी रोका जाना चाहिए लेकिन यह नहीं हो रहा है। मैंने यह भी जांचने के लिए 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); 
  • मैं क्या याद आ रही है?
  • मैं ऐसा क्यों कर सकता हूं कि जब भी एप्लिकेशन को एप्लिकेशन के धागे को रोक दिया जाए (आवेदन द्वारा उत्पन्न धागे) भी बंद हो जाए?

मैं क्योंकि मैं धागा उचित WorkManager जो कंटेनर JNDI द्वारा एक संसाधन के रूप को उजागर करता है उपयोग करके उसे पंजीकृत कर रहा हूँ यह एक अप्रबंधित धागा नहीं माना जाता है लगता है।

अद्यतन: यहां कोड है जो थ्रेड बनाता है।

@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

क्या आप थ्रेड के बजाय WorkManagerTaskExecutor.execute (WorkManagerTaskExecutor कार्य) के लिए एक रननेबल नहीं पारित करना चाहिए? – Hyangelo

+0

एक थ्रेड लागू करता है रननेबल तो एक रननेबल है। मुझे लगता है कि यह समस्या नहीं है। –

+0

निष्पादक कभी भी थ्रेड में थ्रेड ('रन() ') की' स्टार्ट() 'विधि को कॉल नहीं करते हैं, इसलिए आप सामान्य रननेबल (थ्रेड नहीं) का उपयोग भी कर सकते हैं –

उत्तर

6

CommonJ चश्मा के अनुसार, एक WorkManager एक कार्य में उसके isDaemon() विधि सच रिटर्न केवल तभी के निष्पादन को रोकने के लिए प्रयास करेंगे। गैर डेमॉन वर्क्स कम चलने की उम्मीद है ताकि उन्हें रोकने की आवश्यकता न हो।

समस्या यह है कि डिफ़ॉल्ट रूप से, स्प्रिंग द्वारा उपयोग किए जाने वाले कार्य कार्यान्वयन की isDaemon() विधि (और जो वास्तव में रननेबल को लपेटती है) झूठी होती है। आप अपना रननेबल कार्यान्वयन शेड्यूलिंगएवेयर रननेबल बनाकर इसे बदल सकते हैं।

हालांकि, यह पर्याप्त नहीं है। यदि वर्कमैनेजर कार्य को रोकने का फैसला करता है, तो यह कार्य # रिलीज() को कॉल करेगा और यह सुनिश्चित करने के लिए कार्य की जिम्मेदारी है कि यह बंद हो जाए। विशेष रूप से, WorkManager कार्य को निष्पादित करने वाले थ्रेड को बाधित करने का प्रयास नहीं करेगा (क्योंकि यह थ्रेड को रोकने का विश्वसनीय तरीका नहीं है)। समस्या यह है कि वसंत द्वारा उपयोग किए गए कार्य कार्यान्वयन में रिलीज() विधि के लिए एक खाली कार्यान्वयन है, ताकि आप उस सुविधा का उपयोग नहीं कर सकें।

संक्षेप में: यदि आप वसंत का उपयोग करना चाहते हैं, तो यह सुनिश्चित करने का एकमात्र तरीका है कि निष्पादन रोक दिया गया है, इसके लिए अपना स्वयं का तंत्र तैयार करना है।

ध्यान दें कि शेड्यूलिंगएवेयररनेबल का उपयोग करना अभी भी दिलचस्प है, क्योंकि यह वेबस्पियर के थ्रेड मॉनीटर (थ्रेड लटकने के बारे में) द्वारा उत्पन्न चेतावनियों से बच जाएगा।

+0

मैंने WorkManagerTaskExecutor के स्रोत कोड की जांच की और जो आपने लिखा वह सही अर्थ बनाता है। धन्यवाद। मुझे लगता है कि यह बहुत बुरा है कि आप अपने स्वयं के कार्यान्वयन के साथ "रिलीज()" को ओवरराइड नहीं कर सकते हैं। –

संबंधित मुद्दे