最近,我一直在调查令人敬畏的Akka框架,试图了解它并决定它是否适合我的项目。目前,这个应用程序是一个普通的旧java应用程序,它通过调用各种外部c ++可执行文件来执行一些非常复杂的计算(有时计算可能需要数小时才能运行)。在代码中它看起来像这样
public static class Worker extends UntypedActor {
// Run Very Long Process
public void onReceive(Object message) {
if (message instanceof Work) {
Work work = (Work) message;
double result = veryLongProcess(work.getStart(),work.getNrOfElements());
getSender().tell(new Result(result), getSelf());
} else {
unhandled(message);
}
}
}
我的问题是,Akka可以处理演员有时需要几个小时才能从执行中返回吗?
答案 0 :(得分:2)
直接回答你的问题;在这个主题上有一个good article:
同样,如果你有长时间运行的计算,让它们运行在 单独的ExecutionContext用于CPU绑定任务是一个好主意。
该文章有以下示例:
import java.util.concurrent.Executors
import concurrent.ExecutionContext
//I added 'private' for the rest of the example
private val executorService = Executors.newFixedThreadPool(4)
private val executionContext = ExecutionContext.fromExecutorService(executorService)
间接回答,
期货优先
我完全同意Akka Actors对于特定类型的工作是非常有用的工具。谈到缓存,Actors
& Agents
是镇上最好的游戏。
但是,在这种情况下,我建议利用Future
而不是演员。您可以使veryLongProcess成为private
函数。隐私将允许完全控制一次调用该方法的线程数:
def longProcessFut(start : Int, noOfElements : Int) : Future[Result] = Future {
veryLongProcess(start, noOfElements)
}(executionContext)//controls the executing pool of veryLongProcess
简单,简洁,异步。
没有杀死字母,没有重载的接收方法接受任何阳光下的东西,也没有Props,甚至连ActorRef都不是Future的必需品。膨胀,啤酒肚我说!
此外,由于?
:
//Actor user code, too verbose
val longProcessRef = actorSystem actorOf Props[Worker]
val fut : Future[Result] = (longProcessRef ? Work(0,42)).mapTo[Result]
与直接使用期货相比
//happy user code
val fut : Future[Result] = longProcessFut(0, 42)
同样伟大的未来,但卡路里的一半!
您可以按照评论中建议的相同方式控制Future的调度员,这非常好。您甚至可以使用actorSystem.dispatcher
作为Future调度程序来控制调度程序行为。
答案 1 :(得分:0)
如果长时间运行的业务逻辑/算法是增量式的,产生中间结果和/或可以长时间非常运行,那么您可能希望从这里重用优秀的设计片段:{{3} }