2012-01-11 53 views
3

作爲scala和scalaz的新手,使用promise時遇到了問題。我的代碼是這樣的。使用scalaz的承諾時的調用函數

import scalaz._ 
import Scalaz._ 

object Main2 extends Application { 
    def sleeper() = { 
    Thread.sleep(2000) 
    } 
    val message = promise { 
    println("begin") 
    sleeper 
    println("ok") 
    "ok" 
    } 
    Thread.sleep(5000) 
    println("try to get") 
    println(message()) 
} 

此輸出如下,看起來很奇怪。似乎睡眠方法沒有被調用,並且線程被阻塞。 -

begin 
try to get 

但是如果我更換臥鋪打電話給一個內嵌的睡眠,它看起來很好 - 在這裏

object Main2 extends Application { 
    def sleeper() = { 
    Thread.sleep(2000) 
    } 
    val message = promise { 
    println("begin") 
    Thread.sleep(2000) 
    println("ok") 
    "ok" 
    } 
    Thread.sleep(5000) 
    println("try to get") 
    println(message()) 
} 

輸出 -

begin 
ok 
try to get 
ok 

我不明白爲什麼,你能大師請指教?

回答

8

我不能給你一個完整的解釋,但問題似乎與Application特徵的一些問題有關。

簡而言之:Application的構造函數主體運行得太早並處於靜態初始化上下文中。在那一點上,它不能很好地處理線程(如果有的話)。 current Apidoc說:

引用該對象的線程代碼將阻塞,直到靜態初始化完成。但是,因爲擴展應用程序的對象的整個執行過程都是在靜態初始化過程中發生的,所以如果它必須與封閉對象同步,併發代碼將始終發生死鎖。

Scala 2.9開始,有新App特質,它解決大多數問題,因此,所有你需要做的是寫object Main2 extends App,它應該工作。