理解 IO monad

Understanding IO monad

我试图通过 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.

相同

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

因为 IO 是一个单子,所以它仍然会按顺序进行计算。因此,您的照片将始终按此顺序排列。

关于

Neither ContextShift nor ExecutionContext is provided.

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