想知道为什么scalaz Task.runAsyncInterruprupti不会像我期望的那样打断

时间:2016-11-26 01:44:36

标签: scala concurrency task scalaz

我一直在看这个演示文稿https://github.com/indyscala/scalaz-task-intro/blob/master/presentation.md,并对使用Task.runAsyncInterruptibly(稍微修改一下)提供的其中一个代码片段感到困惑:

import java.util.concurrent.atomic.AtomicBoolean

import scalaz.concurrent.Task
import scalaz.{-\/, \/-}

object Junk extends App {

  val neverMind = new AtomicBoolean(false)
  System.out.println(s"neverMind set to $neverMind on thread ${Thread.currentThread().getName}")

  val t = Task {
    System.out.println(s" in task run block on thread ${Thread.currentThread().getName}")
    Thread.sleep(4000)
    System.out.println(s" completed sleep of 40000 ms on thread ${Thread.currentThread().getName}")
  }

  Task.fork(t).
  //t.
    runAsyncInterruptibly({
    case -\/(t) => t.printStackTrace()
    case \/-(()) => println(s"Completed (right) branch of case on thread ${Thread.currentThread().getName}")
  }, neverMind)


  println("sleeping 1000, then set nevermind to true")
  Thread.sleep(1000)
  neverMind.set(true)
  println("woke up. set cancel=true -- expect stack trace not 'Completed' message")

  Thread.sleep(4000)

}

我感到困惑,因为我设置了取消' flag(neverMind.set(true)),但我没有看到堆栈跟踪。延迟{...}内的代码块最终打印成功完成'。这很简单,我相信我犯了一个愚蠢的错误..不知道在哪里!

我向一些同事寻求建议,他们指出我的原始示例没有使用Task.fork()所以我在同一个线程上做了所有事情......呃!好。我纠正了这一点。它仍然不起作用。

提前感谢您提供的任何指导。

1 个答案:

答案 0 :(得分:1)

我认为答案与scalaz的任务/未来内部的蹦床有关​​,因为它只在两个步骤之间检查cancel(请参阅scalaz listenInterruptibly内的Future val t = Task.delay(System.out.println(s" in task run block on thread ${Thread.currentThread().getName}")) .map(_ => Thread.sleep(4000)) .map(_ => System.out.println(s" completed sleep of 40000 ms on thread ${Thread.currentThread().getName}")) 1}}。

如果您将任务更改为:

{{1}}

你会在完成睡眠之前看到它被取消"步。但它似乎还没有调用打印堆栈跟踪的处理程序。