Scala Cats效果-IO异步移位-如何工作? [英] Scala Cats Effects - IO Async Shift - How Does it Work?

查看:102
本文介绍了Scala Cats效果-IO异步移位-如何工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是一些使用 IO Monad 的Scala猫代码:

Here is some Scala cats code using the IO Monad:

import java.util.concurrent.{ExecutorService, Executors}

import cats.effect.IO

import scala.concurrent.{ExecutionContext, ExecutionContextExecutor}
import scala.util.control.NonFatal

object Program extends App {

  type CallbackType = (Either[Throwable, Unit]) => Unit

  // IO.async[Unit] is like a Future that returns Unit on completion.
  // Unlike a regular Future, it doesn't start to run until unsafeRunSync is called.
  def forkAsync(toRun: () => Unit)(executor: ExecutorService): IO[Unit] = IO.async[Unit] { callback: CallbackType =>
    // "callback" is a function that either takes a throwable (Left) or whatever toRun returns (Right).
    println("LalalaAsync: " + Thread.currentThread().getName)
    executor.execute(new Runnable {
      def run(): Unit = {
        val nothing: Unit = toRun() // Note: This line executes the body and returns nothing, which is of type Unit.
        try {
          callback(Right(nothing)) // On success, the callback returns nothing
        } catch {
          case NonFatal(t) => callback(Left(t)) // On failure, it returns an exception
        }
      }
    })
  }

  def forkSync(toRun: () => Unit)(executor: ExecutorService): IO[Unit] = IO.apply {
    println("LalalaSync: " + Thread.currentThread().getName)
    executor.execute(new Runnable {
      def run(): Unit = {
        toRun()
      }
    })
  }

  val treadPool: ExecutorService = Executors.newSingleThreadExecutor()
  val mainThread: Thread = Thread.currentThread()

  val Global: ExecutionContextExecutor = ExecutionContext.global

  /*
  Output:
    1 Hello World printed synchronously from Main.main
    LalalaSync: scala-execution-context-global-12
    Hello World printed synchronously from thread pool.pool-1-thread-1
    LalalaAsync: scala-execution-context-global-12
    Hello World printed asynchronously from thread pool.pool-1-thread-1
    2 Hello World printed synchronously from Global .scala-execution-context-global-12
   */
  val program = for {
    _ <- IO {
      println("1 Hello World printed synchronously from Main." + Thread.currentThread().getName) // "main" thread
    }
    _ <- IO.shift(Global) // Shift to Global Execution Context
    _ <- forkSync { () =>
      println("Hello World printed synchronously from thread pool." + Thread.currentThread().getName) // "pool-1-thread-1" thread
    }(treadPool)
    _ <- forkAsync { () =>
      println("Hello World printed asynchronously from thread pool." + Thread.currentThread().getName) // "pool-1-thread-1" thread
    }(treadPool)
    _ <- IO.shift(Global) // Shift to Global Execution Context
    _ <- IO {
      println("2 Hello World printed synchronously from Global ." + Thread.currentThread().getName) // "scala-execution-context-global-13" thread
    }
  } yield ()

  program.unsafeRunSync()
}

要运行它,您需要添加:

To run it you would need to add:

libraryDependencies ++= Seq(
  "org.typelevel" %% "cats" % "0.9.0",
  "org.typelevel" %% "cats-effect" % "0.3"
),

到您的build.sbt文件.

To your build.sbt file.

注意输出:

  /*
  Output:
    1 Hello World printed synchronously from Main.main
    LalalaSync: scala-execution-context-global-12
    Hello World printed synchronously from thread pool.pool-1-thread-1
    LalalaAsync: scala-execution-context-global-12
    Hello World printed asynchronously from thread pool.pool-1-thread-1
    2 Hello World printed synchronously from Global .scala-execution-context-global-12
 */

基本上,我不了解IO.shift(Global)或IO.async的工作原理.

Basically, I don't understand how IO.shift(Global) or how IO.async works.

例如,为什么为什么在调用"forkAsync"之后,如果不调用"IO.shift(Global)",则随后的同步IO对象将在"pool-1-thread-1"中运行.另外,在此示例中,forkAsync和forkSync有什么区别?它们都从ExecutionContext.global开始,然后在"pool.pool-1-thread-1"中执行Runnable.

For example, why is it that after I call "forkAsync", if I don't call "IO.shift(Global)", the subsequent synchronous IO objects are run in "pool-1-thread-1". Also, what is the difference between forkAsync and forkSync in this example? Both of them start in the ExecutionContext.global and then execute a Runnable in "pool.pool-1-thread-1".

就像forkAsync和forkSync做完全一样的事情还是forkAsync做不同的事情?如果他们在做同样的事情,那么在IO.async中包装代码有什么意义呢?如果他们做的不是同一件事,他们会有什么不同?

Like are forkAsync and forkSync doing the exact same thing or is forkAsync doing something different? If they are doing the same thing, what is the point of wrapping code in IO.async? If they are not doing the same thing, how are they different?

推荐答案

例如,为什么为什么在调用"forkAsync"之后,如果不调用"IO.shift(Global)",则随后的同步IO对象将在"pool-1-thread-1"中运行.

For example, why is it that after I call "forkAsync", if I don't call "IO.shift(Global)", the subsequent synchronous IO objects are run in "pool-1-thread-1".

更重要的问题是,为什么您希望它在全局上评估后续同步IO对象"?

The more important question is why would you expect it to evaluate the "subsequent synchronous IO objects" on global?

IO在内部没有线程池的概念,也不了解global,因此它无法切换回默认线程池,因此确实需要触发手动切换.

IO doesn't have internally the notion of thread-pools, it doesn't know about global, so it cannot shift back to your default thread-pool, therefore you need to trigger a manual shift indeed.

升级到最新版本1.0.0,并且在ContextShift中还有evalOn,它将在指定的线程池上执行IO操作,然后移回您的全局",我想是你想要什么.

Upgrade to the latest version 1.0.0 and you also have evalOn in ContextShift which will execute an IO action on a specified thread-pool and then shift back to your "global", which I suppose is what you want.

在此示例中,forkAsync和forkSync有什么区别?

Also, what is the difference between forkAsync and forkSync in this example?

您的forkSync触发Runnable的执行,但不等待其完成.这是一场大火,忘记了.这意味着后续的连锁动作将不会产生反压力.

Your forkSync triggers the execution of the Runnable, but does not wait for its completion. It's a fire and forget. Which means that subsequent chained actions will not do back-pressuring.

一些建议:

  1. 升级到最新版本(1.0.0)
  2. 在以下位置阅读文档: https://typelevel.org/cats-effect/datatypes /io.html
  1. upgrade to the latest version (1.0.0)
  2. read the docs at: https://typelevel.org/cats-effect/datatypes/io.html

这篇关于Scala Cats效果-IO异步移位-如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆