मेरे पास वस्तुओं का एक संग्रह है, जिस पर मुझे कुछ परिवर्तन करने की आवश्यकता है। वर्तमान में मैं उपयोग कर रहा हूँ:

var myObjects: List<MyObject> = getMyObjects()

myObjects.forEach{ myObj ->
    someMethod(myObj)
}

यह ठीक काम करता है, लेकिन मैं अगले एक पर शुरू करने से पहले, प्रत्येक वस्तु के खत्म होने की प्रतीक्षा करने के बजाय, समानांतर में someMethod() चलाकर इसे तेज करने की उम्मीद कर रहा था।

क्या कोटलिन में ऐसा करने का कोई तरीका है? शायद doAsyncTask या कुछ और के साथ?

मुझे पता है कि यह एक साल पहले पूछा गया था यह संभव नहीं था, लेकिन अब जबकि कोटलिन के पास doAsyncTask जैसे कोरटाइन हैं, मैं उत्सुक हूं कि क्या कोई कोरटाइन मदद कर सकता है

3
Parker 8 अगस्त 2017, 21:25
1
का संभावित डुप्लिकेट
 – 
Pixel Elephant
8 अगस्त 2017, 21:32
2
यह सवाल डेढ़ साल पुराना है, और कोटलिन कोरआउट्स को पेश किए जाने से पहले पूछा गया था
 – 
Parker
8 अगस्त 2017, 21:35
लॉन्च () कोरआउट काम कर सकता हैx
 – 
Sylvain GIROD
8 अगस्त 2017, 22:44
इसके अलावा, आप हमेशा जावा समानांतर धाराओं का उपयोग कर सकते हैं
 – 
Grzegorz Piwowarek
21 अगस्त 2017, 13:12

3 जवाब

हाँ, यह coroutines का उपयोग करके किया जा सकता है। निम्नलिखित फ़ंक्शन संग्रह के सभी तत्वों पर समानांतर में एक ऑपरेशन लागू करता है:

fun <A>Collection<A>.forEachParallel(f: suspend (A) -> Unit): Unit = runBlocking {
    map { async(CommonPool) { f(it) } }.forEach { it.await() }
}

जबकि परिभाषा अपने आप में थोड़ी गूढ़ है, फिर आप इसे आसानी से लागू कर सकते हैं जैसा कि आप उम्मीद करेंगे:

myObjects.forEachParallel { myObj ->
    someMethod(myObj)
}

समानांतर मानचित्र को इसी तरह कार्यान्वित किया जा सकता है, देखें https://stackoverflow.com/a/45794062/1104870

11
Alex Krauss 21 अगस्त 2017, 13:07
वर्तमान में 'CommonPool' तक पहुँचा नहीं जा सकता - यह 'kotlinx.coroutines' में आंतरिक है!
 – 
Strinder
9 जून 2020, 22:40

कोटलिन में जावा स्ट्रीम का उपयोग करना आसान है:

tasks.stream().parallel().forEach { computeNotSuspend(it) }

यदि आप एंड्रॉइड का उपयोग कर रहे हैं, तो आप जावा 8 का उपयोग नहीं कर सकते हैं यदि आप 24 से कम एपीआई के साथ संगत ऐप चाहते हैं।

जैसा कि आपने सुझाव दिया है, आप कोरआउटिन का भी उपयोग कर सकते हैं। लेकिन यह वास्तव में अभी (अगस्त 2017) भाषा का हिस्सा नहीं है और आपको एक बाहरी पुस्तकालय स्थापित करने की आवश्यकता है। बहुत अच्छा उदाहरणों के साथ गाइड

    runBlocking<Unit> {
        val deferreds = tasks.map { async(CommonPool) { compute(it) } }
        deferreds.forEach { it.await() }
    }

ध्यान दें कि कोरआउटिन को गैर-अवरुद्ध बहु-थ्रेडिंग के साथ कार्यान्वित किया जाता है, जिसका अर्थ है कि वे पारंपरिक बहु-थ्रेडिंग से तेज़ हो सकते हैं। मेरे पास स्ट्रीम समानांतर बनाम कोरआउट को बेंचमार्किंग के नीचे कोड है और उस स्थिति में मेरी मशीन पर कोरआउट दृष्टिकोण 7 गुना तेज है। हालांकि आपको यह सुनिश्चित करने के लिए स्वयं कुछ काम करना होगा कि आपका कोड "निलंबित" (गैर-लॉकिंग) है जो काफी मुश्किल हो सकता है। मेरे उदाहरण में मैं सिर्फ delay को कॉल कर रहा हूं जो कि है पुस्तकालय द्वारा प्रदान किया गया एक suspend फ़ंक्शन। नॉन-ब्लॉकिंग मल्टी-थ्रेडिंग हमेशा पारंपरिक मल्टी-थ्रेडिंग की तुलना में तेज़ नहीं होती है। यह तेज़ हो सकता है यदि आपके पास आईओ पर प्रतीक्षा करने के अलावा कई धागे कुछ भी नहीं कर रहे हैं, जो कि मेरा बेंचमार्क कर रहा है।

मेरा बेंचमार्किंग कोड:

import kotlinx.coroutines.experimental.CommonPool
import kotlinx.coroutines.experimental.async
import kotlinx.coroutines.experimental.delay
import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.runBlocking
import java.util.*
import kotlin.system.measureNanoTime
import kotlin.system.measureTimeMillis

class SomeTask() {
    val durationMS = random.nextInt(1000).toLong()

    companion object {
        val random = Random()
    }
}

suspend fun compute(task: SomeTask): Unit {
    delay(task.durationMS)
    //println("done ${task.durationMS}")
    return
}

fun computeNotSuspend(task: SomeTask): Unit {
    Thread.sleep(task.durationMS)
    //println("done ${task.durationMS}")
    return
}

fun main(args: Array<String>) {
    val n = 100
    val tasks = List(n) { SomeTask() }

    val timeCoroutine = measureNanoTime {
        runBlocking<Unit> {
            val deferreds = tasks.map { async(CommonPool) { compute(it) } }
            deferreds.forEach { it.await() }
        }
    }

    println("Coroutine ${timeCoroutine / 1_000_000} ms")

    val timePar = measureNanoTime {
        tasks.stream().parallel().forEach { computeNotSuspend(it) }
    }
    println("Stream parallel ${timePar / 1_000_000} ms")
}

मेरे 4 कोर कंप्यूटर पर आउटपुट:

Coroutine: 1037 ms
Stream parallel: 7150 ms

यदि आप दो compute फ़ंक्शंस में println को अनकम्मेंट करते हैं, तो आप देखेंगे कि गैर-अवरुद्ध कोरआउट कोड में कार्यों को सही क्रम में संसाधित किया जाता है, लेकिन स्ट्रीम के साथ नहीं।

5
toto2 18 अगस्त 2017, 03:17

इसे हल करने के लिए आप RxJava का उपयोग कर सकते हैं।

List<MyObjects> items = getList()

Observable.from(items).flatMap(object : Func1<MyObjects, Observable<String>>() {
    fun call(item: MyObjects): Observable<String> {
        return someMethod(item)
    }
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : Subscriber<String>() {
    fun onCompleted() {

    }

    fun onError(e: Throwable) {

    }

    fun onNext(s: String) {
        // do on output of each string
    }
})

Schedulers.io() को सब्सक्राइब करने से बैकग्राउंड थ्रेड पर कुछ मेथड शेड्यूल हो जाता है।

0
ABS 8 अगस्त 2017, 22:04