2009-09-10 11 views
5

संपादित करें: मैं अब लगता है कि समस्या while (true) पाश अन्य सभी आदेशों पकड़े से संबंधित है के रूप में मैं इसे बाहर टिप्पणी की है और आवेदन तैनात कर रहा हूँ संलग्न अपवाद के बिना। मुझे यकीन है कि कितना यह महत्वपूर्ण है नहीं कर रहा हूँ, लेकिन मेरे ServletContextListener कार्यान्वयन इस तरह दिखता है:एक धागा है कि हर समय अपने आवेदन चल रहा है चलाता कैसे बनाएं

public class BidPushService implements ServletContextListener{

public void contextInitialized(ServletContextEvent sce) { 
//Some init code not relevant, omitted for clarity 
     BidPushThread t= new BidPushThread(); 
     t.setServletContext(sce.getServletContext()); 
     t.run(); 
} 

तो अब धागा जब एप्लिकेशन तैनात है चलाया जाता है, लेकिन क्योंकि while पाश टिप्पणी की है यह कोई वास्तविक अर्थ नहीं है ।

जब मेरा एप्लिकेशन लोड होता है और लगातार (टाइमआउट के बिना) पृष्ठभूमि में थ्रेड चलाने की आवश्यकता होती है तो ऑब्जेक्ट्स के लिए एक निश्चित कतार की जांच करें। बेशक, एक बार वस्तुएं होती हैं, यह "उनका ख्याल रखती है" और फिर कतार की जांच जारी रखती है।

वर्तमान में, मैं ServletContextListener इंटरफ़ेस को कार्यान्वित कर रहा हूं और ऐप लोड होने पर मुझे कॉल किया जा रहा है। इसमें, मैं कुछ रखरखाव की चीजें करता हूं और एक थ्रेड शुरू करता हूं जिसे मैंने java.lang.Thread से विरासत में मिला था।

यहां मेरी समस्या शुरू होती है (या तो मुझे लगता है)। मेरी run() विधि में, मैं एक

while (true) { 
    //some code which doesn't put the thread to sleep ever 
} 

जब मैं सर्वर मैं एक java.util.concurrent.TimeOutException पाने के लिए मेरे एप्लिकेशन को तैनात करने की कोशिश की है। मैं क्या गलत कर रहा हूँ?

क्या मेरे पास हमेशा कोई धागा नहीं चल रहा है? जब ऐप हटा दिया जाता है, तो उस थ्रेड को मेरे ServletContextListener में संबंधित ईवेंट द्वारा रोक दिया जाता है।

मुझे वास्तव में ऐसा कुछ चाहिए जो देरी के बिना कतार की जांच करता रहता है।

किसी भी मदद के लिए बहुत बहुत धन्यवाद!

संपादित करें: यह स्टैक ट्रेस है

GlassFish: deploy is failing= 
    java.util.concurrent.TimeoutException 
    at java.util.concurrent.FutureTask$Sync.innerGet(Unknown Source) 
    at java.util.concurrent.FutureTask.get(Unknown Source) 
    at com.sun.enterprise.jst.server.sunappsrv.SunAppServerBehaviour.publishDeployedDirectory(SunAppServerBehaviour.java:710) 
    at com.sun.enterprise.jst.server.sunappsrv.SunAppServerBehaviour.publishModuleForGlassFishV3(SunAppServerBehaviour.java:569) 
    at com.sun.enterprise.jst.server.sunappsrv.SunAppServerBehaviour.publishModule(SunAppServerBehaviour.java:266) 
    at org.eclipse.wst.server.core.model.ServerBehaviourDelegate.publishModule(ServerBehaviourDelegate.java:948) 
    at org.eclipse.wst.server.core.model.ServerBehaviourDelegate.publishModules(ServerBehaviourDelegate.java:1038) 
    at org.eclipse.wst.server.core.model.ServerBehaviourDelegate.publish(ServerBehaviourDelegate.java:872) 
    at org.eclipse.wst.server.core.model.ServerBehaviourDelegate.publish(ServerBehaviourDelegate.java:708) 
    at org.eclipse.wst.server.core.internal.Server.publishImpl(Server.java:2690) 
    at org.eclipse.wst.server.core.internal.Server$PublishJob.run(Server.java:272) 
    at org.eclipse.core.internal.jobs.Worker.run(Worker.java:55) 

मेरे कोड:

स्वरूपण गंदगी के लिए, लेकिन मेरी "4 स्थानों से मांगपत्र कोड" के जीवन के लिए
public class BidPushThread extends Thread { 
    private ServletContext sc=null; 
    @Override 
    public void run() { 
     if (sc!=null){ 
      final Map<String, List<AsyncContext>> aucWatchers = (Map<String, List<AsyncContext>>) sc.getAttribute("aucWatchers"); 
      BlockingQueue<Bid> aucBids = (BlockingQueue<Bid>) sc.getAttribute("aucBids"); 

       Executor bidExecutor = Executors.newCachedThreadPool(); 
       final Executor watcherExecutor = Executors.newCachedThreadPool(); 
       while(true) 
       { 
       try // There are unpublished new bid events. 
       { 
        final Bid bid = aucBids.take(); 
        bidExecutor.execute(new Runnable(){ 
         public void run() { 
          List<AsyncContext> watchers = aucWatchers.get(bid.getAuctionId()); 
          for(final AsyncContext aCtx : watchers) 
          { 
          watcherExecutor.execute(new Runnable(){ 
           public void run() { 
            // publish a new bid event to a watcher 
            try { 
            aCtx.getResponse().getWriter().print("A new bid on the item was placed. The current price "+bid.getBid()+" , next bid price is "+(bid.getBid()+1)); 
           } catch (IOException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
           } 
           }; 
          }); 
          }       
         } 
        }); 
       } catch(InterruptedException e){} 
       } 

     } 
    } 
    public void setServletContext(ServletContext sc){ 
     this.sc=sc; 
    } 
} 

क्षमा सिर्फ काम नहीं करता है मेरे लिए संपादित करें: 'अवरुद्ध करने' के बारे में पढ़ें और इसे लागू किया गया है, लेकिन मुझे अभी भी सटीक अपवाद और स्टैक ट्रेस मिल रहा है। 'BlockingQueue'

+0

आपको हमें अपवाद का स्टैक ट्रेस देना होगा – skaffman

+0

कृपया अपना कोड दिखाएं। जावा एपीआई में बहुत कम कक्षाएं हैं जो आपके द्वारा प्राप्त अपवाद को फेंक देती हैं, और उनका उपयोग आपके द्वारा प्रदान किए गए विवरण से ज़िंदा नहीं होता है। – SingleShot

+0

आपको निश्चित रूप से अवरुद्ध कतार का उपयोग करना चाहिए। Http://java.sun.com/javase/6/docs/api/java/util/concurrent/BlockingQueue.html के लिए JavaDocs उदाहरण कोड है। –

उत्तर

3

आपका कोड एक नया धागा शुरू नहीं करता है, यह उसी धागे में लूप चलाता है और यही कारण है कि तैनात किए जाने पर आपको टाइमआउट त्रुटि मिल रही है।

धागा शुरू करने के लिए आपको प्रारंभ विधि को कॉल करना होगा, न कि रन विधि।

public void contextInitialized(ServletContextEvent sce) { 
//Some init code not relevant, omitted for clarity 
    BidPushThread t= new BidPushThread(); 
    t.setServletContext(sce.getServletContext()); 
    t.start();// run(); 
} 
+0

वाह, आप बिल्कुल सही हैं! मैंने इसे पहले डेमॉन थ्रेड में बदलकर शुरू करने के लिए बदल दिया "बस क्योंकि" जैसा कि वे कहते हैं और यह काम करना शुरू कर दिया और मुझे नहीं पता था कि यह इसके कारण था। (अब मैंने परीक्षण किया और यही वह है जो मुझे रोक रहा था)। बहुत - बहुत धन्यवाद। – Ittai

+0

मैंने हाल ही में एक ही गलती की है :-( – Serxipc

+0

हा! अच्छी तरह से देखा गया। बस उन चीजों की तरह जो वे मूर्खतापूर्ण जावा परीक्षणों में डाल सकते हैं: एक स्निपेट है जो Thread.run() के बजाय Thread.run() को कॉल करता है और पूछें "इस कोड में क्या गलत है?" –

0

के उपयोग को प्रतिबिंबित करने के() विधि java.langThread.setDaemon पर एक नजर डालें ऊपर कोड बदल यह है कि तुम क्या जरूरत है

3

यह एक बहुत ही बुरा विचार किया जाएगा है हो सकता है। आप एक अच्छे कारण के बिना 100% सीपीयू लोड का कारण बनेंगे।

कतार खाली होने पर सही समाधान शायद धागे को अवरुद्ध करने के लिए है। यह BlockingQueue के साथ मामूली रूप से लागू किया गया है।

+0

और इसके लिए प्रतिक्रिया समय क्या है? मेरा मतलब है कि यह नींद() के साथ लागू नहीं किया गया है, लेकिन अगर मैं सही ढंग से समझता हूं तो 'ब्लॉकिंग क्यूयू' स्वयं थ्रेड उठता है, तो क्या वह तत्काल है? – Ittai

+0

प्रतिक्रिया समय ओएस थ्रेड शेड्यूलर का प्रभुत्व होगा। प्रतीक्षा धागा ओएस स्तर पर अवरुद्ध है। जब कतार भर जाती है, ओएस संकेत दिया जाता है। उस बिंदु पर थ्रेड को चलने योग्य होने से बदल दिया जाता है, और यदि उस समय एक सीपीयू/कोर उपलब्ध होता है तो थ्रेड शायद तुरंत चलाया जाता है। क्योंकि यह इंतजार कर रहा है क्योंकि यह भी प्राथमिकता को बढ़ावा देगा। – MSalters

+0

विंडोज सिस्टम पर, एक यूनिक्स सिस्टम पर एक ब्लॉक से समय प्रतीक्षा करें, जितना 10 मिलीसेकंड हो सकता है। –

5

setDaemon

सारांश:

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

Threads

सारांश: कई मामलों में, क्या हम वास्तव में चाहते हैं पृष्ठभूमि धागे कि एक आवेदन में सरल, समय-समय पर कार्य करने के तैयार करना है। SetDaemon() विधि को थ्रेड को डिमन थ्रेड के रूप में चिह्नित करने के लिए उपयोग किया जा सकता है जिसे मारा जाना चाहिए और जब कोई अन्य एप्लिकेशन थ्रेड नहीं रहें तो त्याग दिया जाए। आम तौर पर, जावा दुभाषिया चलाता है जब तक कि सभी धागे पूरा नहीं हो जाते। लेकिन जब डेमॉन थ्रेड केवल थ्रेड अभी भी जीवित हैं, तो दुभाषिया बाहर निकल जाएगा।

+0

मुझे खेद है कि मैं दो उत्तरों को स्वीकार नहीं कर सकता लेकिन वास्तविकता में आप और एमएसल्टर्स दोनों सही थे, समस्या हल करने के लिए मुझे दोनों गलतियों को ठीक करने की आवश्यकता थी। मैंने आपको वैसे भी एक दिया, प्रयास के लिए धन्यवाद। – Ittai

1
Can't I have a thread which is always running? When the app is removed, 
that thread is stopped by the corresponding event in my ServletContextListener. 

"यह धागा बंद कर दिया है"? कैसे? आपके समय (सत्य) {...} लूप में कोई समाप्ति स्थिति नहीं है। आप इसे कैसे रोक रहे हैं? क्या आप Thread.stop() विधि का उपयोग कर रहे हैं? यह असुरक्षित है और जावा 1.1

यदि आप setDaemon (true) का उपयोग करते हैं, तो आपके ऐप-सर्वर के प्रबंधन टूल का उपयोग करके वेब-ऐप को रोकने के बाद थ्रेड सक्रिय रहेगा। फिर यदि आप वेब-ऐप को पुनरारंभ करते हैं, तो आपको एक और थ्रेड मिल जाएगा। यहां तक ​​कि यदि आप वेब-ऐप को अनावश्यक करने का प्रयास करते हैं, तो थ्रेड चल रहा रहेगा और पूरे वेब-ऐप को कचरा-संग्रहित होने से रोक देगा। फिर अगले संस्करण को पुन: नियोजित करने से आपको स्मृति में सब कुछ की एक अतिरिक्त प्रतिलिपि मिल जाएगी।

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

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