2015-08-27 128 views
4

我在斯卡拉以下代碼:斯卡拉期貨基礎知識

case class Water(temp: Int) 

case class Milk(temp: Int) 

def heatWaterFor(minutes: Int, water: Water) = Future { 
    Thread.sleep(1000) 
    Water(82) 
} 

def boilMilkFor(minutes: Int, milk: Milk) = Future { 
    Thread.sleep(1000) 
    Milk(90) 
} 

def frothMilk(hotwater: Water, hotmilk: Milk) = Future { 
    Thread.sleep(1000) 
    hotmilk 
} 

val start = System.currentTimeMillis() 

val milkMaker = for { 
    water <- heatWaterFor(10, Water(10)) 
    milk <- boilMilkFor(5, Milk(10)) 
    frothed = frothMilk(water, milk) 
    hotMilk <- frothed 
} yield (hotMilk) 

Await.ready(milkMaker, Duration.Inf) 
val end = System.currentTimeMillis() - start 
println(milkMaker.value + " , Time taken: "+((end/1000))+" seconds.") 

我在這裏的目的是並行heatWaterFor(...)boilMilkFor(...),因爲它們是獨立的。但我覺得上面的代碼是連續的,並沒有充分利用期貨的力量。顯然,它運行需要3000毫秒(這是一個額外的證明)。

我在這裏錯過了什麼基本的東西?

回答

1

我猜你正在關注:http://danielwestheide.com/blog/2013/01/09/the-neophytes-guide-to-scala-part-8-welcome-to-the-future.html。最後,它提到了爲什麼這段代碼是順序的,以及如何並行化它(最後一段代碼片段)。

+0

你介意在這裏發佈相關代碼嗎?在SO中只有鏈接的答案是不被接受的。 – dcastro

+0

拿了點,但marstran已經在他的答案中發佈了代碼,所以我不會再發布它。 – markiz

1

檢查this answer

總之,當你使用for這樣,每個變量(watermilkfrothed)的開始時以前準備好評估。這允許在以後的評估中使用先前評估的結果,但它會使計算順序化。

另外(無關)您創建期貨的方法(heatWaterFor等)不使用參數。

3

表達式A被簡化爲一系列map,flatMapwithFilter操作。您的具體表達式可以簡化爲如下形式:

heatWaterFor(10, Water(10)) 
     .flatMap(water => boilMilkFor(5, Milk(10)) 
          .flatMap(milk => frothMilk(water, milk)) 

正如您在此處看到的,在前一個完成時開始執行下一個未來。因此,如果要執行他們都在並行,你需要做這樣的事情:

val heatWater = heatWaterFor(10, Water(10)) 
val boilMilk = boilMilkFor(5, Milk(10)) 

val milkMaker = for { 
    water <- heatWater 
    milk <- boilMilk 
    hotMilk <- frothMilk(water, milk) 
} yield (hotMilk) 

這將啓動heatWaterFor和同時,再啓動frothMilk時,這兩個完成(因爲它依賴對另外兩個期貨的結果)。