blocking
ExecutionContext
पर संकेत के रूप में कार्य करने के लिए है कि निहित कोड अवरुद्ध है और थ्रेड भुखमरी का कारण बन सकता है। इससे थ्रेड पूल को भुखमरी को रोकने के लिए नए धागे को उछालने का मौका मिलेगा। "रनटाइम व्यवहार समायोजित करें" का अर्थ यह है। हालांकि यह जादू नहीं है, और हर ExecutionContext
के साथ काम नहीं करेगा।
import scala.concurrent._
val ec = scala.concurrent.ExecutionContext.Implicits.global
(0 to 100) foreach { n =>
Future {
println("starting Future: " + n)
blocking { Thread.sleep(3000) }
println("ending Future: " + n)
}(ec)
}
यह डिफ़ॉल्ट वैश्विक ExecutionContext
उपयोग कर रहा है:
इस उदाहरण पर विचार। जैसा कोड है, आप देखेंगे कि 100 Future
एस सभी तुरंत निष्पादित किए गए हैं, लेकिन यदि आप blocking
हटाते हैं, तो वे केवल एक समय में कुछ निष्पादित करते हैं। डिफ़ॉल्ट ExecutionContext
नए धागे को बढ़ाकर कॉलिंग कॉल (इस तरह के रूप में चिह्नित) पर प्रतिक्रिया करेगा, और इस प्रकार Future
एस चलाने के साथ अधिभारित नहीं होता है।
अब 4 धागे की एक निश्चित पूल के साथ इस उदाहरण पर नजर:
import java.util.concurrent.Executors
val executorService = Executors.newFixedThreadPool(4)
val ec = ExecutionContext.fromExecutorService(executorService)
(0 to 100) foreach { n =>
Future {
println("starting Future: " + n)
blocking { Thread.sleep(3000) }
println("ending Future: " + n)
}(ec)
}
यह ExecutionContext
नई धागे को उत्पन्न करने को संभालने के लिए नहीं बनाया गया है, और इसलिए मेरी अवरुद्ध blocking
से घिरा कोड के साथ भी, आप देख सकते हैं कि यह अभी भी एक समय में केवल 4 Future
एस पर निष्पादित करेगा। और इसलिए हम कहते हैं कि "प्रदर्शन में सुधार कर सकता है या डेडलॉक्स से बच सकता है" - यह गारंटी नहीं है। जैसा कि हम बाद के ExecutionContext
में देखते हैं, इसकी गारंटी नहीं है।
यह कैसे काम करता है? के रूप में जुड़ा हुआ है, blocking
इस कोड को निष्पादित करता है:
BlockContext.current.blockOn(body)(scala.concurrent.AwaitPermission)
BlockContext.current
को पुन: प्राप्त वर्तमान धागे से BlockContext
, देखा here। BlockContext
आमतौर पर Thread
BlockContext
विशेषता मिश्रित है। स्रोत में देखा गया है, यह या तो ThreadLocal
में संग्रहीत है, या यदि यह वहां नहीं मिला है, तो यह वर्तमान धागे से मिलान पैटर्न है। यदि वर्तमान धागा BlockContext
नहीं है, तो DefaultBlockContext
इसके बजाए उपयोग किया जाता है।
अगला, blockOn
वर्तमान BlockContext
पर कॉल किया जाता है। blockOn
BlockContext
में एक सार विधि है, इसलिए यह कार्यान्वयन इस बात पर निर्भर करता है कि ExecutionContext
इसे कैसे संभालता है। यदि हम implementation for DefaultBlockContext
देखते हैं (जब वर्तमान धागा BlockContext
नहीं है), तो हम देखते हैं कि blockOn
वास्तव में वहां कुछ भी नहीं करता है।तो गैर-BlockContext
में blocking
का उपयोग करने का अर्थ है कि कुछ भी विशेष नहीं किया जाता है, और कोड किसी भी दुष्प्रभाव के साथ चलाया जाता है।
BlockContext
एस के धागे के बारे में क्या? उदाहरण के लिए, global
संदर्भ में, here देखा गया, blockOn
काफी कुछ करता है। गहराई से खोदना, आप देख सकते हैं कि यह ForkJoinPool
हैड के तहत DefaultThreadFactory
के साथ ForkJoinPool
में नए धागे को बढ़ाने के लिए उपयोग किए जाने वाले उसी स्निपेट में परिभाषित किया गया है। BlockContext
(थ्रेड) से blockOn
के कार्यान्वयन के बिना, ForkJoinPool
नहीं जानता कि आप अवरुद्ध कर रहे हैं, और प्रतिक्रिया में अधिक धागे को बढ़ाने की कोशिश नहीं करेंगे।
स्कैला का Await
भी, इसके कार्यान्वयन के लिए blocking
का उपयोग करता है।
ऐसा लगता है कि यह जावा के ['util.concurrent.ForkJoinPool's'] (http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ForkJoinPool.ManagedBlocker पर जादू को पूरी तरह से प्रस्तुत कर रहा है) .html) विवेकाधिकार, कुछ बहिष्कृत स्कैला कोड को छोड़कर। मुझे आश्चर्य है, जावा का कांटा कार्यान्वयन में कैसे शामिल होता है और फिर तय करता है कि एक नया धागा कब उठाना है या नहीं। जावा की थ्रेड स्थितियों में एक मानदंड के रूप में थोड़ा [अपर्याप्त] (http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.State.html#BLOCKED) प्रतीत हो सकता है, जब तक कि कोई भी ब्लॉक_ अवरुद्ध नहीं करेगा एक मॉनिटर लॉक शामिल है। – matanster
ForkJoinPool कैसे तय करता है, आपको [स्रोत] (http://docjar.com/html/api/java/util/concurrent/ForkJoinPool.java.html) में उत्तर मिल सकता है जो संतुष्ट होने से थोड़ा कम है। चीजें बहुत कम स्तर प्राप्त करने लगती हैं। 'addWorker'' ForkJoinWorkerTreadFactory' से नए धागे बना सकता है, जिसे दो स्थानों में कहा जाता है: 'सिग्नलवर्क्स' और 'tryPreBlock'। जिनमें से दोनों बिटवाई तर्क के कुछ रोमांचक मात्रा में शामिल हैं। –
हमें इसे एक अलग प्रश्न (या पुस्तक) के लिए छोड़ दें ... अन्यथा दिखाए जाने तक, मुझे लगता है कि अधिकांश अवरुद्ध एपीआई उस जावा 7 कार्यान्वयन के लिए काफी उपयुक्त हो सकता है, एक लंबे सीपीयू गहन कार्य को छोड़कर भी हो सकता है टाइपसेफ "प्रतिक्रियाशील अनुप्रयोग" दृश्य में "अवरुद्ध" माना जाता है। – matanster