2012-07-17 4 views
16

मेरे पास जावा बाइटकोड के कई उदाहरण हैं, जिनमें से सभी क्लोजर से निष्पादित करना चाहते हैं। बाइटकोड के प्रत्येक अनुक्रम में एक अनंत लूप हो सकता है, जिस स्थिति में मैं इसे कुछ सेकंड के बाद चलाना बंद करना चाहता हूं। मैं इसे करने के साधन के रूप में वायदा देख रहा हूं। मैं कोशिश की है कार्यान्वयन की एक जोड़ी दोनों इस कोड के लिए चारों ओर शिकार करने के बाद:रद्द किए गए क्लोजर वायदा सीपीयू का उपयोग जारी क्यों करते हैं?

(deref (future (loop[a 1] (recur a)) :done!) 1000 :impatient!) 

... और भी https://gist.github.com/3124000

दोनों ही मामलों में कम से कोड, पाश उचित रूप से समय समाप्त हो गया प्रतीत होता है (और बाद के मामले में भविष्य दोनों को किया और रद्द कर दिया गया है), लेकिन मुझे लगता है कि मेरा सीपीयू उपयोग 99% या उससे ऊपर तक बढ़ता है और वहां रहता है। मैं यह भी देखता हूं कि हर बार जब मैं इस कोड को चलाता हूं, तो मेरी जावा प्रक्रिया में अतिरिक्त थ्रेड प्राप्त होता है।

ऐसा लगता है कि भविष्य को रद्द कर दिया जा रहा है, लेकिन कोड अभी भी चल रहा है। मेरे कार्यक्रम में मुझे कुछ बहुत सख्त अनंत लूप (जैसे कि "20 प्रिंट गोटो 10" के बराबर जावा बाइटकोड) चलाने और समय निकालने की आवश्यकता होगी और मेरे पास जो कोड चल रहा है उसे संशोधित करने का विकल्प नहीं है।

कोई विचार क्यों मैं इस व्यवहार को देख रहा हूं; इसे रोकने के लिए मैं क्या कर सकता था; या इस तरह के कोड चलाने और समय के अपने लक्ष्य को समझने के लिए मेरे लिए वैकल्पिक तरीकों?

उत्तर

4

एकमात्र तरीका जो मैंने पाया है कि थ्रेड के अंदर निष्पादित कोड को मारने का एकमात्र तरीका बहिष्कृत .stop विधि का उपयोग करना है। कई मामलों में, जिस कारण से इसे बहिष्कृत किया गया है वह वास्तव में महत्वपूर्ण नहीं है।

मेरे पास ऐसा करने के लिए clojail में एक फ़ंक्शन था। फ़ंक्शन को छीनने या बस लाइब्रेरी में खींचने के लिए स्वतंत्र महसूस करें।

+0

यह वास्तव में उपयोगी लगता है, लेकिन जब मैं करता हूं (थंक-टाइमआउट (लूप [ए 0] (पुनरारंभ ए)) 10000) फ़ंक्शन बस लटकता है और सीपीयू ऊपर जाता है ... 10000ms के बाद भी कोई टाइमआउट नहीं। कोई विचार? –

+0

मैंने जल्द ही बात की; जब मैं थ्रेड ग्रुप बनाता हूं और इसे अपने थंक-टाइमआउट में पास करता हूं, तो आवर्ती फ़ंक्शन वास्तव में बंद हो जाता है। धन्यवाद :) –

+0

थ्रेड ग्रुप की आवश्यकता क्यों है, बस इसे एफएन में लपेटें पर्याप्त है :) (थंक-टाइमआउट (एफएन [] (लूप [ए 0] (रिकर ए)) 10000)) – o0omycomputero0o

1

जावा एपीआई दस्तावेज़ के अनुसार, cancel तुरंत कार्य को रोकने में सक्षम होने के लिए नहीं दिया जाता है।

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

6

थ्रेड रद्दीकरण के लिए जावा की समर्थित तंत्र interrupts है। .stop() विधि एक कारण के लिए हटा दिया गया है - the docs, प्रभावी जावा, अभ्यास में जावा संगामिति देखते हैं, आदि

वास्तव में, FutureTask के कार्यान्वयन (जो future-cancel पीठ) रुकावट आधारित है।

आज के रूप में, प्रत्येक क्लोजर भविष्य को एक असंबद्ध थ्रेड पूल (जैसे send-off क्रियाओं) द्वारा समर्थित किया जाता है। तो तुम धागा रुकावट पुरातन का लाभ उठाने कर सकते हैं:

(def worker 
    (let [p (promise)] 
    {:future (future 
       (let [t (Thread/currentThread)] 
       (deliver p t) 
       (while (not (Thread/interrupted)) 
        (println 42) 
        (Thread/sleep 400)))) 
    :thread @p})) 

अब एक सफलतापूर्वक या तो (.interrupt (:thread worker)) या (future-cancel (:future worker)) निष्पादित कर सकते हैं।

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

मुद्दा यह है कि थ्रेडों को पूर्ववत रूप से मारना आम तौर पर एक बुरा विचार है - यदि आप कार्यों को रद्द करना चाहते हैं, तो आपको कुछ या अन्य तरीकों से उन्हें स्पष्ट रूप से रद्द करने योग्य बनाना होगा। ओटीओएच, आपके विशेष मामले में आप अपारदर्शी बाइटकोड निष्पादित कर रहे हैं, इसलिए .stop() का उपयोग करने से कहीं अधिक विकल्प नहीं है।

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