AtomicInteger recordNumber = new AtomicInteger();
Files.lines(inputFile.toPath(), StandardCharsets.UTF_8)
.map(record -> new Record(recordNumber.incrementAndGet(), record))
.parallel()
.filter(record -> doSomeOperation())
.findFirst()
जब मैंने यह लिखा था तो मैंने मान लिया था कि थ्रेड्स को केवल मैप कॉल के बाद ही देखा जाएगा क्योंकि समानांतर को मैप के बाद रखा गया है। लेकिन फ़ाइल में कुछ पंक्तियों को हर निष्पादन के लिए अलग-अलग रिकॉर्ड नंबर मिल रहे थे।
मैं आधिकारिक जावा स्ट्रीम प्रलेखन और कुछ वेब साइटों को पढ़ने के लिए समझता हूं कि धाराएं हुड के नीचे कैसे काम करती हैं।
कुछ प्रश्न:
स्प्लिटइंटरेटर के आधार पर जावा समानांतर स्ट्रीम काम करती है , जो कि हर कलेक्शन जैसे कि ArrayList, LinkedList आदि द्वारा कार्यान्वित की जाती है। जब हम उन कलेक्शंस में से एक समानान्तर स्ट्रीम का निर्माण करते हैं, तो इसी स्प्लिट इटरेटर का इस्तेमाल कलेक्शन को विभाजित और इट्रेट करने के लिए किया जाएगा। यह बताता है कि समानांतर इनपुट मूल इनपुट स्रोत (फाइल लाइन) स्तर पर क्यों हुआ बल्कि नक्शे के परिणाम (अर्थात रिकॉर्ड पूजो) पर हुआ। क्या मेरी समझ सही है?
मेरे मामले में, इनपुट एक फाइल IO स्ट्रीम है। किस स्प्लिट इटेरेटर का उपयोग किया जाएगा?
इससे कोई फर्क नहीं पड़ता कि हम
parallel()
पाइपलाइन में कहां हैं । मूल इनपुट स्रोत हमेशा विभाजित होगा और शेष मध्यवर्ती संचालन लागू किया जाएगा।इस स्थिति में, जावा को उपयोगकर्ताओं को मूल स्रोत को छोड़कर पाइपलाइन में कहीं भी समानांतर संचालन की अनुमति नहीं देनी चाहिए। क्योंकि, यह उन लोगों के लिए गलत समझ दे रहा है जो नहीं जानते हैं कि जावा स्ट्रीम आंतरिक रूप से कैसे काम करती है। मुझे पता है कि
parallel()
ऑपरेशन को स्ट्रीम ऑब्जेक्ट प्रकार के लिए परिभाषित किया गया होगा और इसलिए, यह इस तरह से काम कर रहा है। लेकिन, कुछ वैकल्पिक समाधान प्रदान करना बेहतर है।उपरोक्त कोड स्निपेट में, मैं इनपुट फ़ाइल में हर रिकॉर्ड के लिए एक पंक्ति संख्या जोड़ने की कोशिश कर रहा हूं और इसलिए इसे आदेश दिया जाना चाहिए। हालांकि, मैं
doSomeOperation()
समानांतर में लागू करना चाहता हूं क्योंकि यह भारी वजन तर्क है। हासिल करने का एक तरीका यह है कि मैं अपना खुद का कस्टमाइज्ड स्प्लिट इटेटर लिखूं। क्या कोई और तरीका है?
Stream
सीधे इंटरफ़ेस में पेश की जाती है और अच्छा कैस्केडिंग के कारण हर ऑपरेशन Stream
फिर से वापस देता है । कल्पना कीजिए कि कोई व्यक्ति आपको कुछ देना चाहता है, Stream
लेकिन पहले से ही इस तरह के एक जोड़े को लागू map
कर दिया है। आप, एक उपयोगकर्ता के रूप में, अभी भी यह तय करने में सक्षम होना चाहते हैं कि इसे समानांतर में निष्पादित किया जाए या नहीं। इसलिए आपके लिए parallel()
अभी भी कॉल करना संभव है , हालांकि स्ट्रीम पहले से मौजूद है।
flatMap
या यदि आप थ्रेड-असुरक्षित विधियों को निष्पादित करते हैं या इसी तरह के आकार को बढ़ाते हैं तो जैसे किनारे मामले हैं ।
Path
स्थानीय फाइल सिस्टम पर होता है और आप हाल ही में JDK का उपयोग कर रहे होते हैं, तो स्प्लिटर को 1024 के गुणक से गुणा करने की तुलना में बेहतर समानांतर प्रसंस्करण क्षमता होगी। लेकिन संतुलित विभाजन कुछ findFirst
परिदृश्यों में काउंटर-उत्पादक भी हो सकता है ...
parallel()
एक सामान्य संशोधक अनुरोध से अधिक कुछ नहीं है जो अंतर्निहित स्ट्रीम ऑब्जेक्ट पर लागू होता है। याद रखें कि केवल एक स्रोत-धारा है यदि आप पाइप के अंतिम संचालन को लागू नहीं करते हैं, जब तक कि "निष्पादित" कुछ भी नहीं है। होने के बाद, आप मूल रूप से जावा डिजाइन विकल्पों पर सवाल उठा रहे हैं। जो राय आधारित है और हम वास्तव में उस पर मदद नहीं कर सकते।