我面临着Scala未来行为不一致的问题。以下是我的代码
package TryFuture
import scala.concurrent.Future
import scala.concurrent.future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scala.util.Random
class FutureCappuccino {
// Some type aliases, just for getting more meaningful method signatures:
type CoffeeBeans = String
type GroundCoffee = String
case class Water(temperature: Int)
type Milk = String
type FrothedMilk = String
type Espresso = String
type Cappuccino = String
// some exceptions for things that might go wrong in the individual steps
// (we'll need some of them later, use the others when experimenting
// with the code):
case class GrindingException(msg: String) extends Exception(msg)
case class FrothingException(msg: String) extends Exception(msg)
case class WaterBoilingException(msg: String) extends Exception(msg)
case class BrewingException(msg: String) extends Exception(msg)
def grind(beans: CoffeeBeans): Future[GroundCoffee] = future {
println("Start grinding with thread: " + Thread.currentThread().getId())
//Thread.sleep(10)
if (beans == "baked beans") throw GrindingException("are you joking?")
println("Finished grinding..")
s"ground coffee of $beans"
}
def heatWater(water: Water): Future[Water] = future {
println("Heating the water with thread: " + Thread.currentThread().getId())
//Thread.sleep(10)
println("It's hot!!")
water.copy(temperature = 85)
}
def frothMilk(milk: Milk): Future[FrothedMilk] = future {
println("milk frothing system engaged! with thread: " + Thread.currentThread().getId())
//Thread.sleep(Random.nextInt(10))
println("shutting down milk frothing system")
s"frothed $milk"
}
def brew(coffee: GroundCoffee, heatedWater: Water): Future[Espresso] = future {
println("happy brewing :) with thread: " + Thread.currentThread().getId())
//Thread.sleep(Random.nextInt(10))
println("it's brewed!")
s"espresso"
}
def combine(espresso: Espresso, frothedMilk: FrothedMilk): Future[String] = future {
println("Combine starting with thread: " + Thread.currentThread().getId())
"Your Cappuccino is ready"
}
// going through these steps sequentially:
def prepareCappuccino() = {
val brewed = for {
coffee <- grind("not baked beans")
water <- heatWater(Water(25))
brewed <- brew(coffee, water)
} yield brewed
brewed
}
}
现在我所期待的是水将等待研磨完成然后酿造将等待研磨和热水完成。但是当我在MacBook上运行这个程序时,我只得到了下面的o / p 用螺纹开始磨削:8然后执行完成。它不是在等待剩下的东西。无法找到我在这里缺少的东西以及它为什么不等待?有什么帮助吗?
答案 0 :(得分:1)
def grind(beans: CoffeeBeans): Future[GroundCoffee] = future {
println("Start grinding with thread: " + Thread.currentThread().getId())
if (beans == "baked beans") throw GrindingException("are you joking?")
...
}
def prepareCappuccino() = {
val brewed = for {
coffee <- grind("baked beans")
water <- heatWater(Water(25))
brewed <- brew(coffee, water)
} yield brewed
brewed
}
grind
方法抛出异常,导致for
表达式导致失败
将来
当grind
传递“not baked beans”时,它会按预期工作。
您的主要线程太快退出。
使用Thread.sleep或Await.result
答案 1 :(得分:0)
最后通过以下更改明确了概念:
package TryFuture
import scala.concurrent.Future
import scala.concurrent.future
import scala.util.{Success,Failure}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scala.util.Random
class FutureCappuccino {
// Some type aliases, just for getting more meaningful method signatures:
type CoffeeBeans = String
type GroundCoffee = String
case class Water(temperature: Int)
type Milk = String
type FrothedMilk = String
type Espresso = String
type Cappuccino = String
// some exceptions for things that might go wrong in the individual steps
// (we'll need some of them later, use the others when experimenting
// with the code):
case class GrindingException(msg: String) extends Exception(msg)
case class FrothingException(msg: String) extends Exception(msg)
case class WaterBoilingException(msg: String) extends Exception(msg)
case class BrewingException(msg: String) extends Exception(msg)
def grind(beans: CoffeeBeans): Future[GroundCoffee] = {
println("Start grinding with thread: " + Thread.currentThread().getId())
Thread.sleep(200)
if (beans == "baked beans") throw GrindingException("are you joking?")
future {
Thread.sleep(200)
s"ground coffee of $beans"
}
}
def heatWater(water: Water): Future[Water] = {
println("Heating the water with thread: " + Thread.currentThread().getId())
Thread.sleep(200)
future {
water.copy(temperature = 85)
}
}
def frothMilk(milk: Milk): Future[FrothedMilk] = {
println("milk frothing system engaged! with thread: " + Thread.currentThread().getId())
Thread.sleep(200)
future {
s"frothed $milk"
}
}
def brew(coffee: GroundCoffee, heatedWater: Water): Future[Espresso] = {
println("happy brewing :) with thread: " + Thread.currentThread().getId())
Thread.sleep(200)
future {
s"espresso"
}
}
def combine(espresso: Espresso, frothedMilk: FrothedMilk): Future[String] = {
println("Combine starting with thread: " + Thread.currentThread().getId())
Thread.sleep(200)
future {
Thread.sleep(20)
"Your Cappuccino is ready"
}
}
// going through these steps sequentially:
def prepareCappuccino() = {
val coffees = grind("not baked beans")
val waters = heatWater(Water(25))
val milks = frothMilk("milk")
val combined = for {
coffee <- coffees
water <- waters
brewed <- brew(coffee, water)
milk <- milks
combined <- combine(brewed, milk)
} yield combined
combined onComplete {
case Success(t) => println("combined is done")
case Failure(t) => t
}
coffees onComplete {
case Success(t) => println("Coffee is done")
case Failure(t) => t
}
combined
}
}
最后====&gt;
val myFutureCappuccino = new FutureCappuccino()
val myCoffee = myFutureCappuccino.prepareCappuccino
Thread.sleep(2000)
myCoffee onComplete{
case Success(t) => println(t)
case Failure(p) => println(p.getMessage())
}
现在对输出很满意:
Start grinding with thread: 1
Heating the water with thread: 1
milk frothing system engaged! with thread: 1
happy brewing :) with thread: 8
Coffee is done
Combine starting with thread: 8
combined is done
Your Cappuccino is ready
在这里分享答案,希望它可以帮助某人。感谢。