2011-03-22 10 views
5

मैं धागे की एक नहीं बल्कि विशाल संख्या एक clojure कार्यक्रम के अंदर बनाया जा रहा है के अंदर एक धागा सो रही है:एक ExecutorService (जावा/Clojure)

(import '(java.util.concurrent Executors)) 
(def *pool* 
    (Executors/newCachedThreadPool)) 

(defn do-something [] 
    ; work 
    Thread/sleep 200 
    ; repeat) 

(dotimes [i 10000] 
    (.submit *pool* do-something)) 

यह मेरे लिए JVMs के बीच एक समय हो गया है और मैं मूल रूप से यहाँ सोच रहा हूँ अगर निष्पादक द्वारा निष्पादित किए जा रहे फ़ंक्शन के अंदर नींद या उपज का उपयोग करने के खिलाफ कोई तर्क है? अगर मैं सही ढंग से समझता हूं, इस मामले में, मेरे श्रमिकों में से प्रत्येक का अपना धागा होता है और इसलिए कोई साइड इफेक्ट नहीं होना चाहिए।

निर्वाहक एक FixedThreadPool उपयोग कर रहा है:

(Executors/newFixedThreadPool 1000) 

हालात और अधिक जटिल हो जाते हैं क्योंकि धागे पूल को वापस नहीं किया जाएगा उनके काम पूरा हो गया है जब तक, अन्य पंक्तिबद्ध कार्यकर्ताओं जिसका अर्थ है यदि पूरा करने के लिए अधिक समय लगेगा धागे सो रहे हैं।

क्या इस उदाहरण में थ्रेडिंग की मेरी समझ सही है?

(नोट: मुझे लगता है मेरी डिजाइन वास्तव में गलत है, लेकिन सिर्फ यकीन है कि मैं सही पेज पर हूँ बनाना चाहते)

उत्तर

7

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

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

आम तौर पर यदि आप आवधिक कार्य कर रहे हैं, तो पूल के बाहर और अग्नि कार्यों को संभालने के लिए बेहतर है, या बेहतर है, तो एक्जिक्यूटर्स/न्यू शेड्यूल्ड थ्रेडपूल से ScheduledExecutorService का उपयोग करें।

समय-आधारित कार्यों को करने के लिए जावा में अन्य मुख्य तंत्र java.util.Timer है, जो उपयोग करने में थोड़ा आसान है लेकिन शेड्यूल किए गए एक्सेलसर्स सेवा के रूप में मजबूत नहीं है।

Clojure से एक अन्य विकल्प स्पष्ट रूप से करने के बजाय आप एक पृष्ठभूमि Clojure द्वारा प्रबंधित थ्रेड में कार्यकर्ता डाल करने के लिए है:

(defn do-task [] 
    (println (java.util.Date.) "doing task")) 

(defn worker [f n wait] 
      (doseq [task (repeat n f)] 
        (f) 
        (Thread/sleep wait))) 

;; use future to execute worker in a background thread managed by Clojure 
(future (worker do-task 10 1000)) 

;; the call to future returns immediately but in the background console 
;; you will see the tasks being run. 
-1

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

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