在我们的项目中,我们需要执行一个侦听队列并在循环中处理即将发生的消息的任务,该循环永远不会完成。代码看起来像:
def processQueue = {
while(true) {
val message = queue.next();
processMessage(message) match {
case Success(_) => ...
case _ => ...
}
}
}
所以我们想在一个单独的线程中运行它。
我可以想象两种方法,一种是使用Thread
,就像我们在Java中所做的那样:
new Thread(new Runnable() { processQueue() }).start();
另一种方法是使用Future
(正如我们现在所做的那样):
Future { processQueue }
我只是想知道在这种情况下使用Future
是否正确,因为据我所知(可能是错误的),Future
意味着要运行一些任务,这将完成或返回一个导致未来的某些时候。但我们的任务永远不会完成。
我也想知道scala中最好的解决方案是什么。
答案 0 :(得分:5)
Future
应该是一个最终会存在的值,所以我认为创建一个永远不会实现的值是没有意义的。它们也是不可改变的,所以将信息传递给它们是禁忌。在Future
中使用一些外部引用的队列听起来就像是黑暗的道路。
你所描述的基本上是一个Akka Actor
,它有自己的FIFO队列,有一个receive
方法来处理消息。它看起来像这样:
import akka.actor._
class Processor extends Actor {
def receive = {
case msg: String => processMessage(msg) match {
case Success(x) => ...
case _ => ...
}
case otherMsg @ Message(_, _) => {
// process this other type of message..
}
}
}
您的应用可以使用Processor
(或其他一些精心设计的演员组)创建此ActorSystem
演员的单个实例:
val akkaSystem = ActorSystem("myActorSystem")
val processor: ActorRef = akkaSystem.actorOf(Props[Processor], "Processor")
并发送消息:
processor ! "Do some work!"
简而言之,使用像Akka这样的并发框架比在单独的线程上创建自己的处理队列更好。 Future
API绝对不是最佳选择。
我建议仔细阅读Akka Documentation以获取更多信息。
答案 1 :(得分:2)
如果你只是运行一个线程(除了主线程),它就没关系了。如果你反复这样做,并且你真的想要很多单独的线程,你应该使用Thread
,因为它就是这样的。期货的构建假设它们将终止,因此您可能会用完池线程。