异步阻塞线程魔术

时间:2015-12-02 14:54:23

标签: scala playframework reactive-programming

我一直在学习游戏,而且我已经掌握了大部分主要概念,但我正在努力应对平台为实现所有这些目标而采取的行动。

特别是,假设我有一个控制器,它会做一些耗费时间的事情。现在我明白了using Futures and asynchronous processing我怎么能让这些东西看起来不会阻塞,但如果它是资源密集型的东西,当然最终它必须阻止某处。根据文件:

  

通过将同步IO包装在Future中,您无法神奇地将同步IO变为异步。如果您无法更改应用程序的体系结构以避免阻塞操作,那么在某些时候必须执行操作,并且该线程将阻塞。因此,除了将操作封装在Future中之外,还需要将其配置为在单独的执行上下文中运行,该上下文已配置了足够的线程来处理预期的并发。

这一点我不明白:如果我通过Future做的某些任务可能在一个单独的线程池中处理,那么Scala / Play在框架中如何/有什么魔力来协调这些线程使得无论哪个线程正在侦听HTTP套接字块足够长时间来执行所有复杂处理(数据库加载,序列化为JSON等等) - 在单独的线程中,然而以某种方式返回到原始阻塞线程必须向客户发回一些请求?

1 个答案:

答案 0 :(得分:2)

免责声明:对于一般问题,这是一个简化的答案,我不想通过进入Play和Akka内部来使这更复杂。

一种方法是让线程监听套接字,但不写入它,让我们称之为AA跨越Future,其本身包含计算所需的所有数据。重要的是不要将执行处理的线程与正在处理的数据混淆,因为数据(内存)由所有线程共享(有时需要显式同步)。未来将由({最终)线程B处理。

现在,在A完成之前,我是否需要B阻止?它可以(并且在许多一般情况下可能是正确的解决方案),但在这种情况下,我们几乎不想停止收听我们的套接字。所以不,我们不会,A忘记信息的一切,继续它的生命。

因此,当B完成时,可能会映射Future或者有一个发送正确响应的侦听器。 B本身可以根据原始邮件中的信息发送它!您只需要小心同步对套接字的访问,以避免与可能已经并行处理前一个或后一个消息的可能线程C发生冲突。

通过让线程产生更多的线程,一些线程写入数据和其他读取数据的队列等等,事情显然会变得更加复杂。(Play,基于Akka,当然包括很多消息队列)。但我希望能说服你,虽然这句话是正确的:

  

你不能通过包装神奇地将同步IO变成异步   它在未来。如果您无法将应用程序的体系结构更改为   避免阻止操作

在许多(大多数?)情况下,应用程序架构的这种变化当然是可能的,当然也是在Play内部完成的。