被叫方Task如何避免在外部范围内更改调度程序(在调用方Task做flatMap中)

时间:2018-06-22 20:52:00

标签: scala task scheduler monix

我正在寻找一种被调用方可以在专用调度程序上执行的方法,并在执行后将调度程序恢复到调用方使用的调度程序。

使用的库和scala:

  • scala-2.12.4
  • monix-"io.monix" %% "monix" % "3.0.0-RC1"
  • 猫-"org.typelevel" %% "cats-core" % "1.0.1"

示例代码:

import monix.eval.Task
import monix.execution.Scheduler
import scala.concurrent.Await
import scala.concurrent.duration.Duration
import monix.execution.Scheduler.Implicits.global
import cats.implicits._

object Test extends App {
  val io1 = Scheduler.io("io1")
  val io2 = Scheduler.io("io2")

  def taskEval(name: String) = Task.eval(println(s"Running eval Task [$name] on thread [${Thread.currentThread().getName}]"))

  def subTask: Task[Unit] = {
    taskEval("subTaskScope").executeOn(io2) <* Task.shift
  }

  val program1 = taskEval("outerScopeBefore").executeOn(io1) *> subTask *> taskEval("outerScopeAfter")
  val program2 = (taskEval("outerScopeBefore") *> subTask *> taskEval("outerScopeAfter")).executeOn(io1)
  val program3 = taskEval("outerScopeBefore").executeOn(io1) *> subTask *> taskEval("outerScopeAfter").executeOn(io1)

  Await.result(program1.runAsync, Duration.Inf)
// Running eval Task [outerScopeBefore] on thread [io1-515]
// Running eval Task [subTaskScope] on thread [io2-516] // << the subTask changes the scheduler of the outerScope 
// Running eval Task [outerScopeAfter] on thread [scala-execution-context-global-517] // << the scheduler jumps to the global default

  println("-----")

  Await.result(program2.runAsync, Duration.Inf)
// Running eval Task [outerScopeBefore] on thread [io1-515]
// Running eval Task [subTaskScope] on thread [io2-516]
// Running eval Task [outerScopeAfter] on thread [io1-515]

  println("-----")

  Await.result(program3.runAsync, Duration.Inf)
// Running eval Task [outerScopeBefore] on thread [io1-515]
// Running eval Task [subTaskScope] on thread [io2-516]
// Running eval Task [outerScopeAfter] on thread [io1-515]]
}

subTask是被调用方,它想在专用调度程序上执行一些计算,但是它不想更改调用方中使用的调度程序。

很明显,subTask可以使用executeOn(io2)来指定要使用io2,然后真诚地使用Task.shift,这将带回调度程序在呼叫者中使用。问题是,除非调用者(即flatMap序列中的program1)再次重置调度程序(如program2)或设置它自己的“ default ”调度程序(如在program3中,将subTask移回 default 的良好意图恢复为最顶层的调度程序(在本例中为 global )。

因此,除非调用者采取了特殊的预防措施(如program2或),否则被调用者实际上无法在专用调度程序上执行工作,而不会冒着更改用于其余执行调用程序的调度程序的风险。 program3)。但是,即使呼叫者采取了这些预防措施,也只会将问题推高到将要呼叫program2program3的那个问题上。

我想做的是使subTask能够指定它要在专用调度程序(io2)中执行,而无需更改调用方使用的调度程序。 subTask

0 个答案:

没有答案