应该很简单,但我不知道该怎么做。我想在当前线程中运行ScalaZ Task。我很惊讶task.run
没有在当前线程上运行,因为它是同步的。
是否可以在当前线程上运行它,以及如何操作?
答案 0 :(得分:0)
自http://timperrett.com/2014/07/20/scalaz-task-the-missing-documentation/以来有一些更新和弃用。
现在推荐的同步调用任务的方法是:
class Timed
{
//...
}
void foo()
{
Timed t_;
//Do the rest of work
}
但请记住,它并不完全在调用者的线程中完成 - 执行是在为任务定义的线程池中执行的,但调用者的线程阻塞直到执行是完了。没有办法让任务在同一个线程中完全运行。
答案 1 :(得分:0)
一般情况下,如果使用Task.async
,则无法使复合Task
始终保持在同一个线程中,因为cb
(回调)可以从任何地方调用(任何地方)线程),所以在链中像:
Task
.delay("aaa")
.map(_ + "bbb")
.flatMap(x => Task.async(cb => completeCallBackSomewhereElse(cb, x)))
.map(_ + "ccc")
.unsafePerformSync
_ + "bbb"
将在来电者的线程中执行
_ + "ccc"
将在Somewhereelse
的帖子中执行,因为scalaz无法控制它。
基本上,这允许Task
成为异步操作的强大工具,因此它甚至可能不知道底层线程池,甚至在没有纯线程和wait / notify的情况下实现行为。
但是,在某些特殊情况下,它可能会作为调用者运行:
1)没有Strategy
/ Task.async
相关内容:
Task.delay("aaa").map(_ + "bbb").unsafePerformSync
unsafePerformSync
使用CountDownLatch等待runAsync
的结果,因此如果路上没有异步/非确定性操作,runAsync
将使用{{3} }}:
/**
* Run this `Future`, passing the result to the given callback once available.
* Any pure, non-asynchronous computation at the head of this `Future` will
* be forced in the calling thread. At the first `Async` encountered, control
* switches to whatever thread backs the `Async` and this function returns.
*/
def runAsync(cb: A => Unit): Unit =
listen(a => Trampoline.done(cb(a)))
2)您可以控制执行策略。所以caller's thread会有所帮助。此外,它已经在scalaz中实现并称为Strategy.sequential
P.S。
1)如果您只是想尽快开始计算,请使用task.now
/ Task.unsafeStart
。
2)如果你想要一些与异步内容不太相关但仍然懒惰和堆栈安全的东西,你可以看看这里(它是Cats库的)this simple Java trick
3)如果您只需要封装副作用 - 请查看http://eed3si9n.com/herding-cats/Eval.html