में kotlinx.coroutines
पुस्तकालय या तो आप का उपयोग कर नए coroutine शुरू कर सकते हैं launch
(साथ join
) या async
(साथ await
)। उनके बीच क्या अंतर है?
में kotlinx.coroutines
पुस्तकालय या तो आप का उपयोग कर नए coroutine शुरू कर सकते हैं launch
(साथ join
) या async
(साथ await
)। उनके बीच क्या अंतर है?
जवाबों:
launch
को आग लगाने और भूल जाने के लिए प्रयोग किया जाता है । यह एक नया सूत्र शुरू करने जैसा है। अंदर कोड तो launch
अपवाद के साथ समाप्त, तो यह की तरह व्यवहार किया जाता है ध्यान में न आया एक सूत्र में अपवाद - आम तौर पर बैकएंड JVM अनुप्रयोगों में stderr करने के लिए मुद्रित और Android एप्लिकेशन दुर्घटनाओं। join
का उपयोग लॉन्च किए गए कोरआउट के पूरा होने की प्रतीक्षा करने के लिए किया जाता है और यह इसके अपवाद का प्रचार नहीं करता है। हालाँकि, एक दुर्घटनाग्रस्त बच्चा कोरटाइन अपने माता-पिता को इसी अपवाद के साथ रद्द कर देता है।
async
एक कॉरआउट शुरू करने के लिए उपयोग किया जाता है जो कुछ परिणाम की गणना करता है । परिणाम एक उदाहरण द्वारा दर्शाया गया है Deferred
और आपको इस पर उपयोग करना चाहिएawait
। async
कोड के अंदर एक अनियोजित अपवाद परिणाम के अंदर संग्रहीत किया जाता है Deferred
और कहीं और वितरित नहीं किया जाता है, यह तब तक चुपचाप गिरा दिया जाएगा जब तक कि संसाधित नहीं किया जाता है। तुम जरूरी नहीं है कि आप asout के साथ शुरू कर दिया है कि coroutine के बारे में भूल जाओ ।
मुझे यह मार्गदर्शिका https://github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md उपयोगी लगती है। मैं आवश्यक भागों का उद्धरण दूंगा
🦄 coroutine
मूल रूप से, कोरआउट हल्के वजन के धागे होते हैं।
तो आप कोरटाइन के बारे में सोच सकते हैं जो एक बहुत ही कुशल तरीके से धागे का प्रबंधन करता है।
🐤 लॉन्च
fun main(args: Array<String>) {
launch { // launch new coroutine in background and continue
delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
println("World!") // print after delay
}
println("Hello,") // main thread continues while coroutine is delayed
Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
}
तो launch
एक बैकग्राउंड थ्रेड शुरू करता है, कुछ करता है, और तुरंत एक टोकन लौटाता है Job
। आप join
इस पर कॉल कर सकते हैं Job
जब तक कि यह launch
धागा पूरा न हो जाए
fun main(args: Array<String>) = runBlocking<Unit> {
val job = launch { // launch new coroutine and keep a reference to its Job
delay(1000L)
println("World!")
}
println("Hello,")
job.join() // wait until child coroutine completes
}
🦆 async
वैचारिक रूप से, async लॉन्च की तरह ही है। यह एक अलग कोरटाइन शुरू करता है जो एक हल्के वजन का धागा है जो अन्य सभी कोरआउट के साथ समवर्ती रूप से काम करता है। अंतर यह है कि लॉन्च एक नौकरी देता है और कोई भी परिणामी मूल्य नहीं रखता है, जबकि एसिंक्स एक आस्थगित देता है - एक हल्के वजन वाला गैर-अवरुद्ध भविष्य जो बाद में एक परिणाम प्रदान करने का वादा करता है।
तो async
एक बैकग्राउंड थ्रेड शुरू करता है, कुछ करता है, और तुरंत एक टोकन लौटाता है Deferred
।
fun main(args: Array<String>) = runBlocking<Unit> {
val time = measureTimeMillis {
val one = async { doSomethingUsefulOne() }
val two = async { doSomethingUsefulTwo() }
println("The answer is ${one.await() + two.await()}")
}
println("Completed in $time ms")
}
आप इसका अंतिम परिणाम प्राप्त करने के लिए एक आस्थगित मूल्य पर .wait () का उपयोग कर सकते हैं, लेकिन आस्थगित भी एक नौकरी है, इसलिए यदि आवश्यक हो तो आप इसे रद्द कर सकते हैं।
तो Deferred
वास्तव में एक है Job
। Https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/index.html देखें
interface Deferred<out T> : Job (source)
🦋 async डिफ़ॉल्ट रूप से उत्सुक है
CoroutineStart.LAZY के मान के साथ एक वैकल्पिक प्रारंभ पैरामीटर का उपयोग करके async के लिए एक आलस्य विकल्प है। यह केवल तब शुरू होता है जब इसके परिणाम में कुछ प्रतीक्षा की आवश्यकता होती है या यदि कोई प्रारंभ कार्य होता है।
launch
और async
नए कॉरआउट शुरू करने के लिए उपयोग किया जाता है। लेकिन, वे उन्हें अलग तरीके से निष्पादित करते हैं।
मैं बहुत बुनियादी उदाहरण दिखाना चाहूंगा जो आपको अंतर को बहुत आसानी से समझने में मदद करेगा
- प्रक्षेपण
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btnCount.setOnClickListener {
pgBar.visibility = View.VISIBLE
CoroutineScope(Dispatchers.Main).launch {
val currentMillis = System.currentTimeMillis()
val retVal1 = downloadTask1()
val retVal2 = downloadTask2()
val retVal3 = downloadTask3()
Toast.makeText(applicationContext, "All tasks downloaded! ${retVal1}, ${retVal2}, ${retVal3} in ${(System.currentTimeMillis() - currentMillis)/1000} seconds", Toast.LENGTH_LONG).show();
pgBar.visibility = View.GONE
}
}
// Task 1 will take 5 seconds to complete download
private suspend fun downloadTask1() : String {
kotlinx.coroutines.delay(5000);
return "Complete";
}
// Task 1 will take 8 seconds to complete download
private suspend fun downloadTask2() : Int {
kotlinx.coroutines.delay(8000);
return 100;
}
// Task 1 will take 5 seconds to complete download
private suspend fun downloadTask3() : Float {
kotlinx.coroutines.delay(5000);
return 4.0f;
}
}
इस उदाहरण में, मेरा कोड btnCount
बटन के क्लिक पर 3 डेटा डाउनलोड कर रहा है और pgBar
सभी डाउनलोड पूरा होने तक प्रगति बार दिखा रहा है । 3 suspend
कार्य हैं downloadTask1()
, downloadTask2()
और downloadTask3()
जो डेटा डाउनलोड करते हैं। इसे अनुकरण करने के लिए, मैंने delay()
इन कार्यों में उपयोग किया है। ये कार्य क्रमशः प्रतीक्षा करते हैं 5 seconds
, 8 seconds
और 5 seconds
क्रमशः।
जैसा कि हमने launch
इन निलंबित कार्यों को शुरू करने के लिए उपयोग किया है , launch
उन्हें क्रमिक रूप से (एक-एक करके) निष्पादित करेगा । इसका मतलब है कि, पूरा downloadTask2()
होने के बाद शुरू होगा downloadTask1()
और पूरा होने के बाद downloadTask3()
ही शुरू होगा downloadTask2()
।
आउटपुट स्क्रीनशॉट के रूप में Toast
, सभी 3 डाउनलोड पूरा करने के लिए कुल निष्पादन समय 5 सेकंड + 8 सेकंड + 5 सेकंड = 18 सेकंड के साथ होगाlaunch
- async
जैसा कि हमने देखा कि सभी 3 कार्यों के लिए launch
निष्पादन होता sequentially
है। सभी कार्यों को पूरा करने का समय था 18 seconds
।
यदि वे कार्य स्वतंत्र हैं और यदि उन्हें अन्य कार्य के संगणना परिणाम की आवश्यकता नहीं है, तो हम उन्हें चला सकते हैं concurrently
। वे एक ही समय में शुरू होते हैं और पृष्ठभूमि में समवर्ती रूप से चलते हैं। इसके साथ किया जा सकता है async
।
async
Deffered<T>
प्रकार का एक रिटर्न देता है , जहां T
डेटा का प्रकार हमारे निलंबन फ़ंक्शन को रिटर्न करता है। उदाहरण के लिए,
downloadTask1()
Deferred<String>
स्ट्रिंग के रूप में वापस आ जाएगा समारोह का प्रकार हैdownloadTask2()
Deferred<Int>
Int के रूप में वापसी होगी फ़ंक्शन का प्रकारdownloadTask3()
वापसी होगी Deferred<Float>
फ्लोट के रूप में समारोह की वापसी प्रकार हैasync
प्रकार Deferred<T>
में लौटे मूल्य को प्राप्त करने के लिए हम प्रकार से वापसी ऑब्जेक्ट का उपयोग कर सकते हैं T
। जिसे await()
कॉल के साथ किया जा सकता है । उदाहरण के लिए नीचे दिए गए कोड की जाँच करें
btnCount.setOnClickListener {
pgBar.visibility = View.VISIBLE
CoroutineScope(Dispatchers.Main).launch {
val currentMillis = System.currentTimeMillis()
val retVal1 = async(Dispatchers.IO) { downloadTask1() }
val retVal2 = async(Dispatchers.IO) { downloadTask2() }
val retVal3 = async(Dispatchers.IO) { downloadTask3() }
Toast.makeText(applicationContext, "All tasks downloaded! ${retVal1.await()}, ${retVal2.await()}, ${retVal3.await()} in ${(System.currentTimeMillis() - currentMillis)/1000} seconds", Toast.LENGTH_LONG).show();
pgBar.visibility = View.GONE
}
इस तरह, हमने सभी 3 कार्यों को समवर्ती रूप से शुरू किया है। इसलिए, मेरे पूर्ण निष्पादन का समय केवल वही होगा 8 seconds
जो समय के लिए है downloadTask2()
क्योंकि यह सभी 3 कार्यों में से सबसे बड़ा है। आप इसे निम्न स्क्रीनशॉट में देख सकते हैंToast message
launch
के लिए है अनुक्रमिक funs, जबकि async
के लिए समवर्ती
launch
और async
नए coroutines शुरू कर देंगे। आप एक एकल कॉरआउट की तुलना कर रहे हैं, जिसमें 3 बच्चों के साथ एक भी कॉरआउट नहीं है। आप प्रत्येक async
इनवोकेशन launch
को बदल सकते हैं और समवर्ती के संबंध में कुछ भी नहीं बदलेगा।
दोनों coroutine बिल्डरों अर्थात् लॉन्च और async मूल रूप से प्रकार के रिसीवर के साथ lambdas हैं CoroutineScope जिसका अर्थ है कि उनके आंतरिक ब्लॉक को एक निलंबित फ़ंक्शन के रूप में संकलित किया गया है, इसलिए वे दोनों एक एसिंक्रोनस मोड में चलते हैं और वे दोनों अपने ब्लॉक को क्रमिक रूप से निष्पादित करेंगे।
लॉन्च और एसिंक्स के बीच अंतर यह है कि वे दो अलग-अलग संभावनाओं को सक्षम करते हैं। लॉन्च बिल्डर एक नौकरी लौटाता है, लेकिन एसिंक्स फ़ंक्शन एक आस्थगित ऑब्जेक्ट लौटाएगा। आप किसी ब्लॉक को निष्पादित करने के लिए लॉन्च का उपयोग कर सकते हैं, जिसे आप किसी भी लौटाए गए मूल्य की अपेक्षा नहीं करते हैं, अर्थात डेटाबेस में लिखना या किसी फ़ाइल को सहेजना या किसी चीज़ को संसाधित करना जो मूल रूप से इसके दुष्प्रभाव के लिए कहा जाता है। दूसरी ओर async जो एक डिफर्ड को वापस करता है जैसा कि मैंने पहले ही कहा था कि इसके ब्लॉक के निष्पादन से एक उपयोगी मूल्य मिलता है, एक ऑब्जेक्ट जो आपके डेटा को लपेटता है, इसलिए आप इसे मुख्य रूप से इसके परिणाम के लिए उपयोग कर सकते हैं लेकिन संभवतः इसके साइड इफेक्ट के लिए भी। NB: आप आस्थगित छीन सकते हैं और फ़ंक्शन प्रतीक्षा का उपयोग करके इसका मूल्य प्राप्त कर सकते हैं, जो आपके बयानों के निष्पादन को तब तक रोक देगा जब तक कि कोई मूल्य वापस नहीं किया जाता है या एक अपवाद नहीं फेंका जाता है!
दोनों coroutine बिल्डर (लॉन्च और Async) रद्द करने योग्य हैं।
कुछ और ?: लॉन्च के साथ हां यदि कोई अपवाद इसके ब्लॉक के भीतर फेंक दिया जाता है, तो कोरटाइन स्वचालित रूप से रद्द कर दिया जाता है और अपवादों को वितरित किया जाता है। दूसरी ओर, अगर ऐसा होता है तो एसिंक्स के साथ अपवाद को आगे प्रचारित नहीं किया जाता है और उसे लौटाए गए डिफरेंट ऑब्जेक्ट के भीतर पकड़ा / संभाला जाना चाहिए।
अधिक coroutines पर https://kotlinlang.org/docs/tutorials/coroutines/coroutines-basic-jvm.html https://www.codementor.io/blog/kotlin-coroutines-6n53b8cbn1
लॉन्च एक नौकरी देता है
async एक परिणाम देता है (आस्थगित नौकरी)
जॉइन खत्म होने तक इंतजार करने के लिए जॉइन के साथ लॉन्च का उपयोग किया जाता है। यह केवल कॉरआउट कॉल ज्वाइन () को स्थगित कर देता है, इस बीच वर्तमान थ्रेड को अन्य काम करने के लिए स्वतंत्र छोड़ देता है (जैसे किसी अन्य कॉरआउट को निष्पादित करना)।
कुछ परिणामों की गणना करने के लिए async का उपयोग किया जाता है। यह एक coroutine बनाता है और Deferred के कार्यान्वयन के रूप में अपना भविष्य परिणाम देता है। जब परिणामी आस्थगित रद्द कर दिया जाता है, तो चल रहे कोरआउट को रद्द कर दिया जाता है।
एक एसिंक्स विधि पर विचार करें जो एक स्ट्रिंग मान लौटाता है। यदि एस्किंट विधि का उपयोग किए बिना प्रतीक्षा की जाती है, तो यह आस्थगित स्ट्रिंग लौटाएगा लेकिन यदि प्रतीक्षा का उपयोग किया जाता है, तो आपको परिणाम के रूप में एक स्ट्रिंग मिलेगी
Async और लॉन्च के बीच महत्वपूर्ण अंतर। जब आप जॉब नहीं करते, तब तक आपकी Toutout खत्म होने के बाद Deferred टाइप T का एक विशेष मान देता है।
Async बनाम लॉन्च Async बनाम लॉन्च डिफ इमेज
लॉन्च / async कोई परिणाम नहीं
परिणाम के लिए async