2010-01-27 10 views
31

स्यूडोकोड में, यहाँ मैं क्या कर रहा है:Process.waitFor(), धागे, और InputStreams

Process proc = runtime.exec(command); 
processOutputStreamInThread(proc.getInputStream()); 
processOutputStreamInThread(proc.getErrorStream()); 
proc.waitFor() 

लेकिन, कभी कभी processOutputStreamInThread नहीं किसी भी उत्पादन देखता और कभी कभी यह नहीं करता है। असल में, विधि कमांड के आउटपुट के BufferedInputStream बनाता है और इसे लॉगर में भेजता है।

मैं क्या दिखाई दे रही है के आधार पर, मेरा अनुमान है कि कि command सब यह धाराओं getInputStream() और getErrorStream() से तंग आ गया में फेंक दिया उत्पादन है की आवश्यकता नहीं है, इस प्रकार धारा खाली हो करने की इजाजत दी।

मेरी परीक्षणों के परिणाम निम्नलिखित प्रश्न हैं:

(1)java.lang.Process में waitFor() निष्पादित कार्यक्रम के उत्पादन से पहले ही रिटर्न को पढ़ लेने की आवश्यकता होती है किया गया है?

प्रलेखन केवल राज्यों:

यदि आवश्यक हो तो प्रतीक्षा करने के लिए, जब तक प्रक्रिया इस Process वस्तु का प्रतिनिधित्व करती समाप्त कर दिया है वर्तमान धागा कारण बनता है। यदि उपप्रोसेस पहले ही समाप्त हो चुका है तो यह विधि तत्काल लौटती है। यदि उपप्रोसेस अभी तक समाप्त नहीं हुआ है, तब तक कॉलिंग थ्रेड अवरुद्ध हो जाएगा जब तक उपप्रोसेस निकलता नहीं है।

(2) किन स्थितियों getInputStream और getErrorStream द्वारा प्रदान की धाराओं के तहत कर बंद किया जा करने की जरूरत है और/या वे अपने आप बंद कर रहे हैं?

प्रलेखन केवल राज्यों:

उपप्रक्रिया की त्रुटि धारा हो जाता है। धारा इस प्रक्रिया ऑब्जेक्ट द्वारा प्रस्तुत प्रक्रिया की त्रुटि आउटपुट स्ट्रीम से पाइप डेटा प्राप्त करती है।

कार्यान्वयन नोट: इनपुट स्ट्रीम को बफर करने के लिए यह एक अच्छा विचार है।

एक user reports कि वह स्वयं धाराओं बंद करने के लिए किया था, लेकिन मैं एक अपवाद समय का संकेत है कि धारा पहले से ही बंद कर दिया है जब मैं ऐसा करने का प्रयास के कम से कम हिस्सा मिलता है।

संपादित करें:getOutputStream से getInputStream बदल गया, जो अब ऊपर मौजूद है।

समाधान: समस्या जा रहा है कुछ मामलों में धागे उत्पादन स्ट्रीम प्रोसेस होने, जब तक के बाद मेरे बहुत अल्पकालिक प्रक्रिया पूरी हो चुकी है नहीं चला होगा मुझे कोई डेटा देने के इनपुट स्ट्रीम में जिसके परिणामस्वरूप इस्तेमाल किया है कि समाप्त हो गया। waitFor निष्पादित कार्यक्रम के आउटपुट के लिए कोई इंतजार नहीं किया। इसके बजाय, प्रोग्राम किसी भी आउटपुट को इकट्ठा करने से पहले भाग गया और समाप्त हो गया।

मैंने धागे का उपयोग किया क्योंकि मुझे यकीन नहीं है कि मैं मानक त्रुटि और मानक आउटपुट पर कितना आउटपुट प्राप्त करने जा रहा था और मैं एक साथ अवरुद्ध किए बिना, दोनों को एक साथ संसाधित करने में सक्षम होना चाहता था, दूसरे में से केवल एक होना चाहिए मौजूद डेटा। लेकिन, क्योंकि मेरे धागे निष्पादित प्रोग्राम के आउटपुट को लगातार पढ़ नहीं सकते हैं, यह एक गैर-समाधान है।

मेरे अंतिम कोडित कुछ इस तरह देखा:

ProcessBuilder pb = new ProcessBuilder(cmdargs); 
pb.redirectErrorStream(true); 
Process proc = pb.start(); 
processOutputStream(proc.getInputStream()); 
proc.waitFor() 

उत्तर

25

यदि आपकी बाहरी प्रक्रिया stdin पर कुछ की अपेक्षा करती है, तो आपको getOutputStream बंद करना होगा। अन्यथा आप हमेशा के लिए waitFor करेंगे।

जावावर्ल्ड से When Runtime.exec() won't article यहां है जो निष्पादन विधि के विभिन्न नुकसान और उनसे कैसे बचें।

मेरे अनुभव से एसटीडीओटीटी और एसटीडीईआरआर को बाल प्रक्रिया (एसईओई तक) का उपभोग करना बेहतर होता है और फिर waitFor में अवरुद्ध होता है। उम्मीद है कि इस बिंदु पर आपको लंबे समय तक इंतजार नहीं करना पड़ेगा।

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

मैं वास्तव में waitFor की कुछ सार्थक टाइमआउट चाहता था हालांकि Process के पास अपने संसाधनों को साफ करने का एक दस्तावेज तरीका था जब आपने इसकी निगरानी छोड़ने का फैसला किया था।

+0

यदि अन्यथा उपयोग किया जाता है तो अन्य धाराएं भी बंद होनी चाहिए? प्रक्रिया समाप्त होने पर वे पूरी तरह बंद हो जाते हैं? –

+0

@ Kaleb मैंने आपके प्रश्न का उत्तर आपके पोस्ट में जोड़ा है। –

+4

जावावर्ल्ड आलेख के बारे में, अंतिम समाधान के साथ एक बग है। यदि कोई प्रक्रिया बहुत जल्दी समाप्त हो जाती है, तो त्रुटि Gobbler और outputGobbler ने अभी तक डेटा चलाया और उपभोग नहीं किया हो सकता है। कोड होना चाहिए: proc.waitFor(); errorGobbler.join(); outputGobbler.join() ;. इसने मुख्य धागे को तब तक प्रतीक्षा करने के लिए मजबूर कर दिया जब तक कि धाराएं इनपुट पढ़ने को समाप्त न करें। –

2

मुझे लगता है कि यह थोड़ा जवाबी सहज है, लेकिन:

getOutputStream उपप्रक्रिया के उत्पादन धारा हो जाता है। पर आउटपुट को इस प्रक्रिया ऑब्जेक्ट द्वारा प्रतिनिधित्व की मानक इनपुट स्ट्रीम में पाइप किया गया है। कार्यान्वयन नोट: आउटपुट स्ट्रीम के लिए यह एक अच्छा विचार है। रिटर्न: सबप्रोसेस के सामान्य इनपुट में आउटपुट स्ट्रीम से जुड़ा हुआ है।

मैंने पढ़ा है कि मुख्य प्रक्रिया से आउटपुट धारा के रूप में और उप-प्रक्रिया के मानक इनपुट से जुड़ा हुआ है, इसलिए जब आप getOutputStream को लिखने()। बारे में() आप वास्तव में stdin पर लिख रहे हैं।

क्या आप संभवतः .getInputStream() का उपयोग करना चाहते हैं?

रिटर्न: उपप्रोसेसर के सामान्य आउटपुट से जुड़ी इनपुट स्ट्रीम।

Process.Waitfor का सवाल है() API डॉक्स कहते हैं:

,, प्रतीक्षा करने के लिए वर्तमान धागा का कारण बनता है, तो आवश्यक जब तक प्रक्रिया इस प्रक्रिया वस्तु का प्रतिनिधित्व करती समाप्त है। यदि उपप्रोसेस पहले ही समाप्त हो गया है तो यह विधि तुरंत लौटाती है। यदि उपप्रोसेस अभी तक समाप्त नहीं हुआ है, तो थ्रेड को उपप्रोसेज निकास तक अवरुद्ध कर दिया जाएगा।

मैं धागा इस में कहा जाता है इस तरह के एक समय तक बाधित कर दी जाएगी प्रक्रिया का निष्पादन पूरा होने कहेंगे - आप अभी भी अन्य सूत्र के आधार पर इस स्तर पर उत्पादन संसाधित हो रहा हो या वे पहले समाप्त कर दिया है हो सकता है आपके धागा रिटर्न।

+0

'getOutputStream()' जो मेरे प्रश्न में था, वह एक टाइपो था। यह वास्तव में मेरे वास्तविक कोड में 'getInputStream() 'था और संकलित नहीं होता क्योंकि प्रसंस्करण कार्य' इनपुटस्ट्रीम 'की अपेक्षा करता है। –

+0

मुझे लगता है कि आप अभी भी मेरे धागे के बारे में बिल्कुल सही हैं आउटपुट प्रसंस्करण। अधिकांश समय, जब मैं डीबग मोड में भाग गया, तो सब कुछ सफलतापूर्वक भाग गया क्योंकि सबकुछ धीमा हो गया था। डीबगर के बिना चलते समय, यह आमतौर पर असफल हो जाता है। मैं बाद में अपना कामकाज पोस्ट करूंगा। –

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