2009-11-17 20 views
15

मेरे पास vals: Iterable[T] और किसी भी प्रासंगिक साइड इफेक्ट्स के बिना एक लंबे समय तक चलने वाला फ़ंक्शन है: f: (T => Unit)। अभी यह स्पष्ट रास्ते में vals लिए आवेदन किया है:स्कैला में समवर्ती मानचित्र/foreach

vals.foreach(f)

मैं f के लिए कॉल चाहते हैं समवर्ती (उचित सीमा के भीतर) किया जाना चाहिए। क्या स्काला बेस लाइब्रेरी में कहीं कोई स्पष्ट कार्य है? की तरह कुछ:

Concurrent.foreach(8 /* Number of threads. */)(vals, f)

जबकि f यथोचित लंबी चलने वाली है, यह इतना छोटा हो कि मैं प्रत्येक कॉल के लिए एक धागा लागू की भूमि के ऊपर नहीं करना चाहती है, तो मैं एक धागा पूल के आधार पर कुछ के लिए देख रहा हूँ।

उत्तर

10

मैं Futures जवाब पसंद है। हालांकि, यह एक साथ निष्पादित करेगा, यह असीमित रूप से भी वापस आ जाएगा, जो शायद आप नहीं चाहते हैं।

import scala.actors.Futures._ 

vals map { x => future { f(x) } } foreach { _() } 
+8

सावधान रहें कि 'vals' एक सख्त संग्रह है - यदि यह आलसी है (और स्कैला 2.7 में इसमें' रेंज 'वर्ग शामिल है), वायदा तब तक नहीं बनाए जाएंगे जब तक कि प्रत्येक को' foreach 'द्वारा आवश्यक न हो, और समानांतर में कुछ भी नहीं होगा। –

+0

मुझे लगता है कि हम 'मानचित्र' और वर्तमान 'foreach' के बीच एक और' foreach' कॉल इंजेक्शन द्वारा उस समस्या को हल कर सकते हैं। इस प्रकार: 'vals नक्शा {x => भविष्य {f (x)}} foreach {x => x} foreach {_()} ' –

+0

यह एक नक्शा होगा जिसे हमें इंजेक्ट करना होगा, एक और foreach नहीं? और यह मुझे स्पष्ट नहीं है कि आलसी संग्रह का नक्शा सख्त है। आरे को कॉल करने का सबसे सुरक्षित तरीका हो सकता है। –

3

मुझे स्कैला.एक्टर्स का उपयोग करके कुछ समस्याएं थीं। स्कैला 2.8 में फ्यूचर्स (जब मैंने चेक किया तो यह छोटी थी)। का उपयोग करते हुए जावा libs सीधे, हालांकि मेरे लिए काम किया:

final object Parallel { 
    val cpus=java.lang.Runtime.getRuntime().availableProcessors 
    import java.util.{Timer,TimerTask} 
    def afterDelay(ms: Long)(op: =>Unit) = new Timer().schedule(new TimerTask {override def run = op},ms) 
    def repeat(n: Int,f: Int=>Unit) = { 
    import java.util.concurrent._ 
    val e=Executors.newCachedThreadPool //newFixedThreadPool(cpus+1) 
    (0 until n).foreach(i=>e.execute(new Runnable {def run = f(i)})) 
    e.shutdown 
    e.awaitTermination(Math.MAX_LONG, TimeUnit.SECONDS) 
    } 
} 
2

मैं scala.actors.Futures का उपयोग करेंगे:

vals.foreach(t => scala.actors.Futures.future(f(t))) 
13

ScalazparMap है: सही दृष्टिकोण इस प्रकार होगा।

import scalaz.Scalaz._ 
import scalaz.concurrent.Strategy.Naive 

यह एक parMap विधि के साथ (Iterable सहित) हर functor से लैस होगा, ताकि आप बस कर सकते हैं::

vals.parMap(f) 

तुम भी parFlatMap, parZipWith, आदि प्राप्त इस प्रकार आप इसे प्रयोग करेंगे

2

Functional Java की नवीनतम रिलीज में कुछ उच्च-आदेश समवर्ती विशेषताएं हैं जिनका आप उपयोग कर सकते हैं।

import fjs.F._ 
import fj.control.parallel.Strategy._ 
import fj.control.parallel.ParModule._ 
import java.util.concurrent.Executors._ 

val pool = newCachedThreadPool 
val par = parModule(executorStrategy[Unit](pool)) 

और फिर ...

par.parMap(vals, f) 

shutdownpool करना न भूलें।

0

आप स्कैला मानक पुस्तकालय से Parallel Collections का उपयोग कर सकते हैं। वे साधारण संग्रह की तरह हैं, लेकिन उनके संचालन समानांतर में चलते हैं। कुछ संग्रह ऑपरेशन करने से पहले आपको केवल par कॉल डालना होगा।

import scala.collection._ 

val array = new Array[String](10000) 
for (i <- (0 until 10000).par) array(i) = i.toString 
9

2009 से जवाब है, जो नए स्काला में नहीं रह रहे हैं अभी भी पुराने scala.actors.Futures._ का उपयोग से कई। जबकि अक्का पसंदीदा तरीका है, समानांतर () का उपयोग करने के लिए एक और अधिक पठनीय तरीका है।सममूल्य) संग्रह:

vals.foreach { v => f(v) }

vals.par.foreach { v => f(v) }

वैकल्पिक रूप से हो जाता है, parMap का उपयोग कर चेतावनी है कि आप हमेशा की तरह Scalaz आयात करने के लिए याद करने के लिए * जरूरत के साथ यद्यपि अधिक संक्षिप्त दिखाई दे सकता है। हमेशा की तरह, स्कैला में एक ही चीज़ करने के लिए एक से अधिक तरीके हैं!

+0

अब यह स्वीकार्य उत्तर होना चाहिए –

संबंधित मुद्दे