2012-05-12 19 views
9

नहीं चलाते हैं, मैं नए स्कैला 2.10 futures feature पर उदाहरण पुन: पेश करने की कोशिश कर रहा था। कोड मैं का उपयोग किया है है:स्कैला 2.10 में संभावित बग: फ्यूचर्स

import scala.concurrent.Future 
import scala.concurrent.future 

object Test { 
    def main(args: Array[String]) { 
    println("Test print before future") 
    val s = "Hello" 
    val f = future {s + " future!"} 
    f onSuccess {case v => println(v)} 
    println("Test print after future") 
    } 
} 

मुद्रण के बजाय:

Test print before future 
Hello future! 
Test print after future 

यह बस प्रिंट:

Test print before future 
Test print after future 

कारण है कि मैं इस व्यवहार है की कोई भी विचार? स्कैला कंपाइलर का मेरा संस्करण 2.10.0-20120507 है।

उत्तर

28

मुद्दा यह है कि आप को क्रियान्वित कर रहे हैं कि एक स्टैंडअलोन कार्यक्रम, जिसका मुख्य रूप कार्यकर्ता धागे में से एक "हैलो भविष्य" निष्पादित कर सकता है इससे पहले थ्रेड समाप्त हो रहा है! println। (थ्रेड जो नए वायदा लाइब्रेरी स्पॉन डिमन थ्रेड हैं)।

तुम भी Await वस्तु (scala.concurrent में भी) भविष्य f के पूर्ण होने तक उपयोग कर सकते हैं प्रतीक्षा करने के लिए:

import scala.concurrent._ 
import scala.concurrent.util._ 

object Test { 
    def main(args: Array[String]) { 
    println("Test print before future") 

    val s = "Hello" 
    val f = future {s + " future!"} 
    f onSuccess {case v => println(v)} 
    println("Test print after future") 

    Await.ready(f, Duration.Inf) 
    } 
} 

यह मुद्रित कर सकते हैं:

Test print before future 
Test print after future 
Hello future! 

या, यह "मुद्रित कर सकते हैं हैलो भविष्य! " थ्रेड शेड्यूल के आधार पर "भविष्य के बाद टेस्ट प्रिंट" से पहले।

import scala.concurrent._ 
import scala.concurrent.util._ 

object Test { 
    def main(args: Array[String]) { 
    println("Test print before future") 

    val s = "Hello" 
    val f = future {s + " future!"} 
    f onSuccess {case v => println(v)} 

    Await.ready(f, Duration.Inf)   

    println("Test print after future") 
    } 
} 

कौन सा प्रिंट होगा::

Test print before future 
Hello future! 
Test print after future 

हालांकि, ध्यान दें कि आप का उपयोग करते हैं

इसी तरह, आप इस प्रकार जब तक f पिछले println से पहले पूरा हो गया है प्रतीक्षा करने के लिए मुख्य थ्रेड मजबूर कर सकते हैं Await, आप अवरुद्ध कर रहे हैं। यह निश्चित रूप से यह सुनिश्चित करने के लिए समझ में आता है कि आपका मुख्य अनुप्रयोग धागा समाप्त नहीं होता है, लेकिन आम तौर पर अन्यथा आवश्यक होने तक इसका उपयोग नहीं किया जाना चाहिए।

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

+0

आप जानते हैं? मैंने सोचा था कि इस कारण का कारण बिल्कुल उसी तरह है जब आप गोरोटाइन से निपट रहे हैं: आप मुख्य ब्लॉक को बंद करने से पहले गोरोटाइन द्वारा भेजे गए संदेश की प्रतीक्षा करने के लिए चैनल का उपयोग करते हैं। –

+0

@ हेदर क्या एक से अधिक भविष्य के लिए इंतजार करना संभव है? – 66CLSjY

1

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

Test print before future 
Test print after future 
Hello future! 

और फिर बाहर निकल जाता है (मैं स्काला 2.10.0-एम 3 उपयोग कर रहा हूँ)। आपको यह परीक्षण करने के लिए यह कर सकते - बस कुछ सेकंड के लिए नींद में मुख्य निष्पादन धागा डाल और देखें कि क्या Hello future! छपा है:

import scala.concurrent.Future 
import scala.concurrent.future 

object Test { 
    def main(args: Array[String]) { 
     println("Test print before future") 

     val s = "Hello" 
     val f = future {s + " future!"} 
     f onSuccess {case v => println(v)} 

     println("Test print after future") 

     Thread.sleep(3000) 
     println("Test print at the end.") 
    } 
} 
1

मैं इसे सामान्य रूप से जोड़ना चाहता हूं, एक और संभावना है कि वायदा नहीं चल रहे हैं: थ्रेड पूल सीमा को मारना।

आपके मामले में यह शायद सिर्फ एक समय मुद्दा था के रूप में अन्य लोगों ने बताया है, लेकिन भविष्य में संदर्भ के रूप में इस उदाहरण पर विचार करें:

import scala.concurrent._ 
import scala.concurrent.ExecutionContext.Implicits.global 
import scala.concurrent.duration.Duration 


object FutureDebug { 
    def main(args: Array[String]) { 

    for (i <- Range(0, 4)) { 
     future { 
     while (true) { 
      Thread.sleep(1000) 
      println("I'm doing stupid things in a future") 
     } 
     } 
    } 

    println("(1) reached? yes") 
    val fut = future { 
     for (i <- Range(0, 1000)) { 
     println("never reached " + i) 
     } 
     3.14 
    }  
    println("(2) reached? yes") 
    Await.result(fut, Duration.Inf) 
    println("(3) reached? no") 
    } 
} 

मेरी मशीन डिफ़ॉल्ट वैश्विक निष्पादन संदर्भ सिर्फ 4 धागे है पर। चूंकि कार्यकर्ता धागे 4 गैर-अर्थ वायदा को निष्पादित करने में व्यस्त हैं, इसलिए नीचे का भविष्य कभी नहीं चलेगा। यही कारण है कि किसी को डिफ़ॉल्ट निष्पादन संदर्भ से सावधान रहना चाहिए और एकाधिक (वास्तव में) लंबे समय तक चलने वाले वायदा से निपटने के दौरान specify one's own execution context पर सर्वोत्तम होना चाहिए।

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