我一直在看这个演示文稿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()所以我在同一个线程上做了所有事情......呃!好。我纠正了这一点。它仍然不起作用。
提前感谢您提供的任何指导。
答案 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}}
你会在完成睡眠之前看到它被取消"步。但它似乎还没有调用打印堆栈跟踪的处理程序。