2009-08-21 7 views
16

नीचे दिए गए कोड में मैं 20 धागे बना देता हूं, उनमें से प्रत्येक को एक संदेश, नींद, और एक और संदेश प्रिंट करें। मैं धागे को अपने मुख्य धागे में शुरू करता हूं और फिर सभी धागे में भी शामिल होता हूं। मैं उम्मीद करता हूं कि "सभी किए गए" संदेश को केवल सभी धागे समाप्त होने के बाद ही मुद्रित किया जाएगा। फिर भी सभी धागे किए जाने से पहले "सब कुछ किया जाता है" मुद्रित हो जाता है। क्या कोई इस व्यवहार को समझने में मेरी मदद कर सकता है?Thread.join व्यवहार के रूप में व्यवहार नहीं किया गया क्योंकि मुझे स्केल

धन्यवाद।

def ttest() = { 
    val threads = 
     for (i <- 1 to 5) 
     yield new Thread() { 
      override def run() { 
      println("going to sleep") 
      Thread.sleep(1000) 
      println("awake now") 
      } 
     } 

    threads.foreach(t => t.start()) 
    threads.foreach(t => t.join()) 
    println("all done") 
    } 

यहाँ आउटपुट है: केंट

यहाँ कोड है

going to sleep 
all done 
going to sleep 
going to sleep 
going to sleep 
going to sleep 
awake now 
awake now 
awake now 
awake now 
awake now 
+0

मैं इस प्रश्न को उखाड़ फेंक रहा हूं क्योंकि समझ के लिए विशिष्ट बातचीत, श्रेणियां और धागे एक सामान्य पुनरावर्ती त्रुटि पैटर्न प्रतीत होते हैं। –

उत्तर

7

अपने कोड में, threads टाल रहा है - हर बार जब आप यह पुनरावृति, for जनरेटर अभिव्यक्ति चलाया जाता है नए सिरे से। इस प्रकार, आप वास्तव में वहां 10 धागे बनाते हैं - पहला foreach 5 बनाता है और उन्हें शुरू करता है, दूसरा foreach 5 और बनाता है (जो शुरू नहीं होते हैं) और उनसे जुड़ता है - क्योंकि वे नहीं चल रहे हैं, join तुरंत लौटता है। एक स्थिर स्नैपशॉट बनाने के लिए आपको for के परिणाम पर toList का उपयोग करना चाहिए।

+0

धन्यवाद, पावेल। वह बिल्कुल था। मुझे नहीं पता कि उपरोक्त वास्तव में उत्तर कैसे हटाएं। – Kent

11

यह काम करता है अगर आप एक List में Range परिणत:

def ttest() = { 
    val threads = 
     for (i <- 1 to 5 toList) 
     yield new Thread() { 
      override def run() { 
      println("going to sleep") 
      Thread.sleep(1000) 
      println("awake now") 
      } 
     } 

    threads.foreach(t => t.start()) 
    threads.foreach(t => t.join()) 
    println("all done") 
    } 

समस्या यह है कि "1 to 5" एक Range है, और पर्वतमाला तो बात करने के लिए, "सख्त" नहीं हैं। अच्छी अंग्रेजी में, जब आप पर Range पर विधि को कॉल करते हैं, तो यह प्रत्येक मान की गणना नहीं करता है। इसके बजाए, यह एक ऑब्जेक्ट उत्पन्न करता है - स्कैला 2.7 पर एक RandomAccessSeq.Projection - जिसमें मैप में पारित फ़ंक्शन का संदर्भ है और दूसरा मूल श्रेणी में है। इस प्रकार, जब आप परिणामस्वरूप सीमा के तत्व का उपयोग करते हैं, तो आपके द्वारा मानचित्र पर पारित फ़ंक्शन मूल सीमा के संबंधित तत्व पर लागू होता है। और यह हर बार जब आप परिणामस्वरूप सीमा के किसी तत्व का उपयोग करेंगे।

इसका मतलब है कि प्रत्येक बार जब आप t के तत्व को संदर्भित करते हैं, तो आप new Thread() { ... } नया कॉल कर रहे हैं। चूंकि आप इसे दो बार करते हैं, और श्रेणी में 5 तत्व हैं, आप 10 धागे बना रहे हैं। तुम पहले 5 पर शुरू, और दूसरा 5.

पर शामिल होते हैं तो यह भ्रामक है, नीचे दिए गए उदाहरण को देखो:

scala> object test { 
    | val t = for (i <- 1 to 5) yield { println("Called again! "+i); i } 
    | } 
defined module test 

scala> test.t 
Called again! 1 
Called again! 2 
Called again! 3 
Called again! 4 
Called again! 5 
res4: scala.collection.generic.VectorView[Int,Vector[_]] = RangeM(1, 2, 3, 4, 5) 

scala> test.t 
Called again! 1 
Called again! 2 
Called again! 3 
Called again! 4 
Called again! 5 
res5: scala.collection.generic.VectorView[Int,Vector[_]] = RangeM(1, 2, 3, 4, 5) 

हर बार जब मैं t प्रिंट (स्काला आरईपीएल प्रिंट res4 और res5 होने से), उपजित अभिव्यक्ति का फिर से मूल्यांकन किया जाता है। यह बहुत अलग-अलग तत्वों के लिए होता है:

scala> test.t(1) 
Called again! 2 
res6: Int = 2 

scala> test.t(1) 
Called again! 2 
res7: Int = 2 

संपादित

स्काला 2.8 के रूप में, Range, सख्त हो तो सवाल में कोड काम करेंगे के रूप में मूल रूप से उम्मीद होगी।

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