理解IO Monad

7

我正在通过cats.effect.IO的例子来理解异步计算,并且有一些误解。不安全的方法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一样。


@erip 无关标签已删除。 - St.Antario
2个回答

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

IO.shift 需要 ContextShiftExecutionContext。而 unsafeRunAsync 则不需要。 - St.Antario
啊...我刚刚自己尝试了一下,看到了区别。微妙的事情...谢谢。 - St.Antario

2
unsafeRunSyncunsafeRunAsync之间的区别在于线程是否被阻塞。在IO单子中使用Thread.sleep会强制线程阻塞,从而强制其同步行为。
但是由于IO是一个单子,它仍然会按顺序执行计算。因此,您的打印输出将始终按照顺序进行。

没错。我刚才明白了,我们可以移除阻塞操作并获得异步行为。谢谢。 - St.Antario

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接