了解Scalaz未来和任务的一点帮助
我试图理解scalaz并发包背后的思想和目的,主要是Future和Task类,但在某些应用程序中使用它们时,它现在远不是简单的顺序模拟,而了解Scalaz未来和任务的一点帮助,scala,asynchronous,concurrency,scalaz,scalaz7,Scala,Asynchronous,Concurrency,Scalaz,Scalaz7,我试图理解scalaz并发包背后的思想和目的,主要是Future和Task类,但在某些应用程序中使用它们时,它现在远不是简单的顺序模拟,而scala.concurrent.Future,工作得更好。任何人都可以分享他使用scalaz编写并发/异步应用程序的经验,基本上如何正确使用它的async方法?我从源代码中了解到,async没有使用单独的线程,比如调用scalaz works中的标准future或fork/apply方法,那么为什么它被称为async?这是否意味着为了与scalaz实现真正的
scala.concurrent.Future
,工作得更好。任何人都可以分享他使用scalaz编写并发/异步应用程序的经验,基本上如何正确使用它的async
方法?我从源代码中了解到,async没有使用单独的线程,比如调用scalaz works中的标准future
或fork/apply
方法,那么为什么它被称为async
?这是否意味着为了与scalaz实现真正的并发性,我必须始终调用fork(现在(…)
或apply
?我不是scalaz专家,但我会尽力帮你一点忙。让我试着逐一回答你的问题:
1)任何人都可以分享他使用scalaz编写并发/异步应用程序的经验,基本上如何正确使用其异步方法?
我们首先来看一下async
签名:
def async[A](监听:(A=>Unit)=>Unit):未来[A]
这一点一开始可能有点神秘,所以像往常一样,查看测试以了解可能的用例是个好主意。在里面
您可以找到以下代码:
"when constructed from Future.async" ! prop{(n: Int) =>
def callback(call: Int => Unit): Unit = call(n)
Future.async(callback).run must_==
}
从签名Future.async
我们知道,只需使用签名(A=>Unit)=>Unit
的函数构造新的未来。这实际上意味着Future.async将作为参数函数,该函数对给定回调进行所有必需的计算,并将结果传递给该回调。重要的是要注意,
Future.async
本身不运行任何计算,它只为以后运行它们准备结构
2)据我从源代码中了解,async没有像调用standard future那样使用单独的线程,也没有使用scalaz works中的fork/apply方法,那么为什么它被称为async呢?
你说得对。只有fork
和apply
似乎在使用线程运行任何东西,查看包含隐式池:ExecutorService
的签名时很容易注意到这一点。我不能在这里代表作者发言,但我想async与回调有关。这意味着,您将使用异步回调,而不是阻塞Future以最终获得结果
3)这是否意味着为了与scalaz实现真正的并发性,我必须始终调用fork(现在是(…)或apply?
据我所知,是的。请注意,当您使用语法Future(x)
创建Future时,您使用的是apply
方法,因此这是一种默认行为(这很好)
如果你想更好地理解Scalaz期货的设计,我可以推荐你阅读。我相信这本书是由Scalaz的主要贡献者写的,第7章讨论了为纯函数并行库设计API。它与Scalaz Future并不完全相同,但您可以看到许多相似之处。您还可以阅读Timothy Perrett关于Scalaz任务和Future的精彩文章,其中涵盖了许多不太明显的细节。
async
用于将基于回调的异步API改编为Future
。它被称为async
,因为预期它将与异步运行的东西一起使用,可能会从另一个线程调用回调。这是“真正的”并发,前提是您调用的API确实异步使用它(例如,我使用AWS SDK的异步部分,如AmazonSimpleDBAsyncClient,使用Future.async
)
如果您想直接从scalaz
任务
API获得“真正”的并发性,您需要使用fork
或gatherUnordered
,因为许多API默认为安全/确定性和可重启的,仅当明确请求时才使用并发。使用map和flatMap编写任务时,不使用fork可以获得性能优势,请参阅:
这个答案可以通过参考博客来改进,但要在这里包含相关信息。没有办法依赖未来存在的博客。