我正在尝试通过cats.effect.IO
示例来理解异步计算,并产生了一些误解。 unsafe
方法unsafeRunAsync
似乎异步运行基础效果(我希望提供一些ContextShift
)。但是该方法看起来像这样:
final def unsafeRunAsync(cb: Either[Throwable, A] => Unit): Unit =
IORunLoop.start(this, cb)
ContextShift
和ExecutionContext
均未提供。这是非常简单的示例:
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
相同。
答案 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)
unsafeRunSync
和unsafeRunAsync
之间的区别在于线程是否被阻塞。您通过在Thread.sleep
monad的正文中使用IO
来强制线程阻塞。这样,您将迫使它同步运行。
由于IO
是monad,因此它仍将按顺序进行计算。因此,您的打印将始终按照该顺序进行。