RxJava अनुसूचियों के लिए मामलों का उपयोग करें


253

RxJava में 5 अलग-अलग अनुसूचियों में से चुनने के लिए हैं:

  1. तत्काल () : एक अनुसूचक बनाता है और वापस करता है जो वर्तमान थ्रेड पर तुरंत कार्य निष्पादित करता है।

  2. trampoline () : बनाता है और वर्तमान समय पूरा होने के बाद निष्पादित करने के लिए वर्तमान थ्रेड पर काम करने वाले शेड्यूल को बनाता है।

  3. newThread () : एक शेड्यूलर बनाता और वापस करता है जो प्रत्येक यूनिट के काम के लिए एक नया थ्रेड बनाता है।

  4. अभिकलन () : कम्प्यूटेशनल कार्य के लिए एक शेड्यूलर बनाता और वापस करता है। इसका उपयोग इवेंट-लूप, प्रोसेसिंग कॉलबैक और अन्य कम्प्यूटेशनल काम के लिए किया जा सकता है। इस अनुसूचक पर IO- बद्ध कार्य न करें। शेड्यूलर का उपयोग करें। इसके बजाय io ()

  5. io () : आईओ-बाउंड कार्य के लिए एक शेड्यूलर बनाता और वापस करता है। कार्यान्वयन एक एक्सेक्यूटर थ्रेड-पूल द्वारा समर्थित है जो आवश्यकतानुसार बढ़ेगा। इसका उपयोग अतुल्यकालिक रूप से अवरुद्ध आईओ के प्रदर्शन के लिए किया जा सकता है। इस अनुसूचक पर कम्प्यूटेशनल कार्य न करें। शेड्यूलर का उपयोग करें। संगणना () के बजाय।

प्रशन:

पहले 3 अनुसूचियां बहुत आत्म व्याख्यात्मक हैं; हालाँकि, मैं गणना और io के बारे में थोड़ा उलझन में हूँ ।

  1. वास्तव में "IO- बाउंड वर्क" क्या है? क्या इसका उपयोग धाराओं ( java.io) और फ़ाइलों ( java.nio.files) से निपटने के लिए किया जाता है ? क्या इसका उपयोग डेटाबेस प्रश्नों के लिए किया जाता है? इसका उपयोग फ़ाइलों को डाउनलोड करने या REST API तक पहुँचने के लिए किया जाता है?
  2. कैसे गणना () नए थ्रेड () से अलग है ? क्या यह है कि सभी गणना () कॉल हर बार एक नए (पृष्ठभूमि) धागे के बजाय एक एकल (पृष्ठभूमि) धागे पर होती हैं?
  3. IO काम करते समय कम्प्यूटेशन () को कॉल करना क्यों बुरा है ?
  4. कम्प्यूटेशनल काम करते समय io () को कॉल करना क्यों बुरा है ?

जवाबों:


332

महान प्रश्न, मुझे लगता है कि प्रलेखन कुछ और विवरण के साथ कर सकता है।

  1. io()एक अनबाउंड थ्रेड-पूल द्वारा समर्थित है और इस तरह की चीज है जिसे आप गैर-कम्प्यूटेशनल रूप से गहन कार्यों के लिए उपयोग करेंगे, यह वह सामान है जो सीपीयू पर अधिक भार नहीं डालता है। तो फ़ाइल सिस्टम के साथ बातचीत का अंत, एक अलग मेजबान पर डेटाबेस या सेवाओं के साथ बातचीत अच्छे उदाहरण हैं।
  2. computation()उपलब्ध प्रोसेसर की संख्या के बराबर आकार के साथ एक बंधे हुए थ्रेड-पूल द्वारा समर्थित है। यदि आपने उपलब्ध प्रोसेसर (कहते हैं newThread()) का उपयोग करते हुए अधिक से अधिक समानांतर में सीपीयू गहन कार्य को शेड्यूल करने का प्रयास किया है, तो आप थ्रेड निर्माण ओवरहेड और संदर्भ स्विचिंग ओवरहेड के लिए एक प्रोसेसर के लिए धागे के रूप में हैं और यह संभवतः एक बड़ा प्रदर्शन हिट है।
  3. computation()सीपीयू गहन कार्य के लिए छोड़ना सबसे अच्छा है अन्यथा आपको अच्छा सीपीयू उपयोग नहीं मिलेगा।
  4. io()2. चर्चा की गई कारण के लिए कम्प्यूटेशनल काम के लिए कॉल करना बुरा io()है। अनबाउंड है और यदि आप io()समानांतर में एक हजार कम्प्यूटेशनल कार्यों को शेड्यूल करते हैं, तो उन हजार कार्यों में से प्रत्येक का अपना एक धागा होगा और सीपीयू के लिए प्रतिस्पर्धा हो सकती है संदर्भ स्विचिंग लागत।

5
RxJava स्रोत के साथ परिचित के माध्यम से। यह लंबे समय से मेरे लिए भ्रम का स्रोत था और मुझे लगता है कि इस संबंध में प्रलेखन की आवश्यकता है।
डेव मोटेन

2
@IgorGanapolsky मुझे लगता है कि ऐसा कुछ है जो आप शायद ही कभी करना चाहेंगे। काम की प्रत्येक इकाई के लिए एक नया धागा बनाना शायद ही कभी दक्षता के लिए अनुकूल होता है क्योंकि धागे निर्माण और फाड़ने के लिए महंगे होते हैं। आप आमतौर पर थ्रेड्स का उपयोग करना चाहते हैं जो संगणना () और अन्य शेड्यूलर्स करते हैं। केवल नए समय () में वैध उपयोग हो सकता है (कम से कम मैं सोच सकता हूं) अलग-थलग, असंगत, लंबे समय से चल रहे कार्यों को बंद कर रहा है। फिर भी मैं उस परिदृश्य के लिए io () का उपयोग कर सकता हूं।
tnn

4
क्या आप एक उदाहरण दिखा सकते हैं कि ट्रम्पोलिन () कहाँ उपयोगी होगा? मैं इस अवधारणा को समझता हूं, लेकिन मैं एक ऐसे परिदृश्य का पता नहीं लगा सकता, जिसका मैं अभ्यास करूं। यह एकमात्र अनुसूचक है जो अभी भी मेरे लिए एक रहस्य है
tmn

32
नेटवर्क कॉल के लिए Schedulers.io () का उपयोग करें और यदि आपको एक साथ नेटवर्क कॉल की संख्या को निर्धारित करने की आवश्यकता है, तो Scheduler.from (Executors.newFixedThreadPool (n)) का उपयोग करें।
डेव मोटेन

4
आप सोच सकते हैं कि timeoutडिफ़ॉल्ट रूप से computation()आप एक थ्रेड को रोक रहे होंगे, लेकिन ऐसा नहीं है। कवर के तहत computation()एक ScheduledExecutorServiceसमय का उपयोग करता है इसलिए विलंबित क्रियाएं अवरुद्ध नहीं होती हैं। इस तथ्य computation()को देखते हुए यह एक अच्छा विचार है क्योंकि यदि यह दूसरे धागे पर होता तो हम थ्रेड स्विचिंग लागत के अधीन होते।
डेव मोटेन

3

सबसे महत्वपूर्ण बिंदु यह है कि दोनों अनुसूचियों .io और अनुसूचियों। विचलन का समर्थन निर्बाध थ्रेड पूल द्वारा किया जाता है, जैसा कि प्रश्न में वर्णित अन्य के विपरीत है। यह विशेषता केवल शेड्यूलर। एफ्रॉम ( एक्जिक्यूटर) द्वारा साझा की जाती है, यदि एक्जिक्यूटर को न्यू कैश्ड थ्रेडपूल (ऑटो- रिकॉल थ्रेड पूल के साथ अनबाउंड ) के साथ बनाया गया है ।

जैसा कि पिछली प्रतिक्रियाओं और वेब पर कई लेखों में बहुतायत से समझाया गया है, उनके नाम में कार्य के प्रकार के लिए अनुकूलित किए जाने पर, Schedulers.io और Schedulers.computation का सावधानीपूर्वक उपयोग किया जाएगा। लेकिन, मेरी बात के लिए, वे सबसे महत्वपूर्ण भूमिका प्रतिक्रियाशील धाराओं के लिए वास्तविक संगामिति प्रदान करना है

नए लोगों के विश्वास के विपरीत, प्रतिक्रियाशील धाराएं स्वाभाविक रूप से समवर्ती नहीं हैं बल्कि स्वाभाविक रूप से अतुल्यकालिक और अनुक्रमिक हैं। इस कारण से, Schedulers.io का उपयोग केवल तब किया जाएगा जब I / O ऑपरेशन अवरुद्ध हो रहा है (उदाहरण के लिए: Apache IOUtils FileUtils.readFileAsString (...) जैसे अवरुद्ध कमांड का उपयोग करके इस प्रकार कॉलिंग थ्रेड को तब तक फ्रीज किया जाएगा जब तक कि ऑपरेशन न हो। किया हुआ।

जावा एसिंक्रोनसफाइलचैनलाइन (...) जैसी एक एसिंक्रोनस विधि का उपयोग करना ऑपरेशन के दौरान कॉलिंग थ्रेड को ब्लॉक नहीं करेगा, इसलिए एक अलग थ्रेड का उपयोग करने का कोई मतलब नहीं है। वास्तव में, Schedulers.io थ्रेड वास्तव में अतुल्यकालिक संचालन के लिए एक अच्छा फिट नहीं है क्योंकि वे एक इवेंट लूप नहीं चलाते हैं और कॉलबैक कभी नहीं होगा ... कहा जाता है।

डेटाबेस एक्सेस या रिमोट एपीआई कॉल के लिए एक ही तर्क लागू होता है। यदि आप कॉल करने के लिए एसिंक्रोनस या प्रतिक्रियाशील API का उपयोग कर सकते हैं तो Schedulers.io का उपयोग न करें।

वापस संगति के लिए। I / O ऑपरेशन को अतुल्यकालिक या समवर्ती रूप से करने के लिए आपके पास एक async या प्रतिक्रियाशील API तक पहुंच नहीं हो सकती है, इसलिए आपका एकमात्र विकल्प एक अलग थ्रेड पर कई कॉल को प्रेषण करना है। अफसोस, प्रतिक्रियाशील धाराओं उनके सिरों पर अनुक्रमिक हैं लेकिन अच्छी खबर यह है कि है flatMap () ऑपरेटर उनके मूल में संगामिति लागू कर सकते हैं

कंसीडर को स्ट्रीम निर्माण में बनाया जाना चाहिए, आमतौर पर फ्लैटपाइप () ऑपरेटर का उपयोग करके । यह शक्तिशाली ऑपरेटर आंतरिक रूप से आपके फ्लैटपाइप () एम्बेडेड फ़ंक्शन <T, R> को एक बहु-थ्रेडेड संदर्भ प्रदान करने के लिए कॉन्फ़िगर किया जा सकता है । यह संदर्भ शेड्यूलर .io या शेड्यूलर.कॉम विचलन जैसे बहु-थ्रेडेड शेड्यूलर द्वारा प्रदान किया जाता है ।

RxJava2 पर लेख में और अधिक जानकारी प्राप्त Schedulers और संगामिति जहां कोड नमूना और कैसे क्रमिक रूप से और समवर्ती Schedulers का उपयोग करने पर विस्तृत व्याख्या के मिल जाएगा।

उम्मीद है की यह मदद करेगा,

Softjake


2

यह ब्लॉग पोस्ट एक उत्कृष्ट उत्तर प्रदान करता है

ब्लॉग पोस्ट से:

Schedulers.io () एक अनबाउंड थ्रेड पूल द्वारा समर्थित है। इसका उपयोग गैर-सीपीयू-गहन I / O प्रकार के लिए किया जाता है जिसमें फ़ाइल सिस्टम के साथ इंटरैक्शन, नेटवर्क कॉल, डेटाबेस इंटरैक्शन करना, आदि शामिल हैं। इस थ्रेड पूल का उपयोग अतुल्यकालिक रूप से अवरुद्ध IO के लिए किया जाता है।

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

Schedulers.newThread () शेड्यूल किए गए कार्य की प्रत्येक इकाई के लिए एक नया थ्रेड बनाता है। यह अनुसूचक महंगा है क्योंकि हर बार नया धागा पैदा होता है और कोई पुन: उपयोग नहीं होता है।

Schedulers.from (निष्पादन निष्पादक) बनाता है और निर्दिष्ट निष्पादक द्वारा समर्थित एक कस्टम अनुसूचक देता है। थ्रेड पूल में एक साथ थ्रेड्स की संख्या को सीमित करने के लिए, शेड्यूलर.फ्रॉम (एक्जिक्यूटर्स .newFixedThreadPool (n)) का उपयोग करें। यह गारंटी देता है कि यदि सभी थ्रेड्स पर कब्जा किए जाने पर कोई कार्य निर्धारित है, तो इसे कतारबद्ध किया जाएगा। पूल में धागे तब तक मौजूद रहेंगे जब तक कि यह स्पष्ट रूप से बंद नहीं हो जाता।

मुख्य धागा या AndroidSchedulers.mainThread () RxAndroid एक्सटेंशन लाइब्रेरी द्वारा RxJava को प्रदान किया जाता है। मुख्य थ्रेड (जिसे UI थ्रेड के रूप में भी जाना जाता है) वह है जहां उपयोगकर्ता इंटरैक्शन होता है। जानकी गैर-प्रतिक्रियाशील UI या इससे भी बदतर, एप्लिकेशन नॉट रिस्पॉन्सिंग (ANR) डायलॉग को रोकने के लिए इस थ्रेड को ओवरलोड नहीं करने के लिए ध्यान रखा जाना चाहिए।

Schedulers.single () RxJava 2 में नया है। यह अनुसूचक अनुरोध किए गए क्रम में क्रमिक रूप से निष्पादित एकल थ्रेड द्वारा समर्थित है।

Schedulers.trampoline () एक FIFO (फर्स्ट इन, फर्स्ट आउट) तरीके से कार्यों को अंजाम दे रहा है। कॉल स्टैक बढ़ने से बचने के लिए पुनरावृत्ति को लागू करते समय इसका अक्सर उपयोग किया जाता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.