了解IO monad

时间:2018-11-14 14:56:02

标签: scala functional-programming scala-cats

我正在尝试通过cats.effect.IO示例来理解异步计算,并产生了一些误解。 unsafe方法unsafeRunAsync似乎异步运行基础效果(我希望提供一些ContextShift)。但是该方法看起来像这样:

final def unsafeRunAsync(cb: Either[Throwable, A] => Unit): Unit =
  IORunLoop.start(this, cb)

ContextShiftExecutionContext均未提供。这是非常简单的示例:

object TestIo extends App {
  println(s"Main thread = ${Thread.currentThread().getName}")
  val io = IO {
    println(s"Effect thread = ${Thread.currentThread().getName}")
    Thread.sleep(1000)
  }
  io.unsafeRunAsync(_ => println(s"Callback thread = ${Thread.currentThread().getName}"))
  println(s"Finished")
}

输出为

Main thread = main
Effect thread = main
Callback thread = main
Finished

如您所见,这里的所有内容都在 主线程 中运行 同步 。您能解释一下unsafeRunAsync吗?在我看来,它与unsafeRunSync相同。

2 个答案:

答案 0 :(得分:4)

关于

  

既未提供ContextShift也未提供ExecutionContext。

cats.effect.IO中有一个上下文切换

查看此博客:https://www.jaspervanzandbeek.com/scala/cats-io-monad/

这里是一个例子:

def blockingOperation(): String = {
  // Read from file
  ...
}

val result: IO[String] = for {
  _ <- IO.shift(executionContextForBlockingOperations)
  result <- IO { blockingOperation() }
  _ <- IO.shift(mainExecutionContext)
} yield result

答案 1 :(得分:2)

unsafeRunSyncunsafeRunAsync之间的区别在于线程是否被阻塞。您通过在Thread.sleep monad的正文中使用IO来强制线程阻塞。这样,您将迫使它同步运行。

由于IO是monad,因此它仍将按顺序进行计算。因此,您的打印将始终按照该顺序进行。