2012-05-12 15 views
9

Yeni Scala 2.10 futures feature'daki örneği yeniden oluşturmaya çalışıyordum. Kullandığım kodudur:Scala'da olası hata 2.10: Futures koşmuyor

yerine baskı
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 

It basitçe baskılar:

Test print before future 
Test print after future 

Ben bu davranışı neden Herhangi bir fikir? Scala derleyicim sürümüm 2.10.0-20120507'dir.

cevap

28

sorun, yürütme olduğunuzu olduğunu asıl bağımsız bir program olarak iş parçacığı iş parçacıklarından biri "Merhaba gelecek" i yürütmeden önce iş parçacığı sona eriyor println. (Yeni gelecek kütüphanesinin geliştirdiği konular daemon konularıdır). o Alo" yazdırabilirsiniz,

Test print before future 
Test print after future 
Hello future! 

Veya:

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) 
    } 
} 

Bu yazdırabilirsiniz:

Ayrıca gelecek f tamamlanana kadar beklemek (ayrıca scala.concurrent olarak) Await nesneyi kullanabilirsiniz gelecek!" İş parçacığı programına bağlı olarak "Gelecekte yazdırmayı sınama" dan önce.

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") 
    } 
} 

basacaktır hangisi:

Test print before future 
Hello future! 
Test print after future 

Ancak kullandığınızda unutmayın

Aynı şekilde, f son println önce tamamlanıncaya kadar aşağıdaki gibi beklemek ana iş parçacığı zorlayabilir Await, engellediniz. Bu elbette, ana uygulama parçanızın sonlandırılmamasını sağlamak için mantıklıdır, ancak genellikle gerekli olmadıkça kullanılmamalıdır.

(Await nesnesi, bunlar gibi durumlar için gerekli bir çıkış bölmesidir, ancak uygulama kodu boyunca anlamını kaygı duymadan kullanmak, daha yavaş, daha az paralel yürütme ile sonuçlanabilir. Belirtilen sipariş, örneğin, Future'da andThen ve map yöntemleri gibi başka alternatifler vardır.

+0

Biliyor musunuz? Bunun hakkında düşündüm çünkü goroutines ile uğraşırken aynı yoldaydı: Ana bloğu kapatmadan önce goroutines tarafından gönderilen bir mesajı beklemek için kanalları kullanıyorsunuz. –

+0

@Heather Birden fazla geleceği beklemek mümkün mü? – 66CLSjY

1

Buradaki sorunun zamanlama olduğunu düşünüyorum. Muhtemelen gelecekteki kodunuz ayrı deamon iş parçacığında çalışıyor. Uygulamanın çok hızlı tamamlandığını düşünüyorum ve bu deamon ipliği düzgün bir şekilde yürütmek için yeterli zamana sahip değil (uygulama deamon ipliklerinin bitmesini beklemiyor). Ama bu aynı zamanda sisteme bağlı davranış. (Ben Scala 2.10.0-M3 kullanıyorum)

Test print before future 
Test print after future 
Hello future! 

ve sonra çıkar: Benim için yazdırır. Bunu test etmek için aşağıdakileri deneyin - sadece birkaç saniye uykusunda ana yürütme iş parçacığı koymak ve Hello future! basılı olup olmadığını görmek:

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

Sadece şunu eklemek isterim: genel olarak, futuresların çalışmadığı başka bir olasılık daha var: İplik havuzu limitine çarpmak. Senin durumunda

muhtemelen Diğerleri işaret olarak sadece bir zamanlama sorunu olduğunu, ancak ileride referans olarak bu örneği ele alalım: benim makinede varsayılan küresel yürütme içeriği sadece 4 konu vardır On

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") 
    } 
} 

. İşçi iş parçacıkları, 4 duygusuz geleceği yürütmekle meşgul olduğundan, aşağıdaki gelecek asla çalışmayacaktır. Bu nedenle, varsayılan yürütme içeriğine dikkat edilmeli ve birden çok (gerçekten) uzun vadeli gelecekle uğraşırken en iyisi specify one's own execution context olmalıdır.