【问题标题】:play - how to wrap a blocking code with futuresplay - 如何用期货包装阻塞代码
【发布时间】:2016-06-02 00:56:24
【问题描述】:

我试图了解这两种方法在功能方面的区别。

class MyService (blockService: BlockService){
   def doSomething1(): Future[Boolean] = {
       //do
       //some non blocking
       //stuff
       val result = blockService.block()
       Future.successful(result)
   }

   def doSomething2(): Future[Boolean] = {
       Future{
          //do
          //some non blocking
          //stuff
          blockService.block()
       }
   }
}

据我了解,两者之间的区别在于哪个线程是将被阻塞的实际线程。

所以如果有一个线程:thread_1 执行something1,thread_1 将被阻塞,而如果一个thread_1 执行something2,一个新线程将运行它-thread_2,而thread_2 将被阻塞被屏蔽了。

这是真的吗?

如果是这样,那么就没有编写此代码的首选方法了吗?如果我不在乎最终会阻塞哪个线程,那么最终结果将是相同的。 dosomething1 写这段代码的方式似乎很奇怪,我会选择dosomething2

有意义吗?

【问题讨论】:

    标签: scala asynchronous playframework future


    【解决方案1】:

    是的,doSomething1doSomething2 会阻塞不同的线程,但根据您的情况,这是一个重要的决定。

    正如@AndreasNeumann 所说,您可以在doSomething2 中拥有不同的执行上下文。想象一下,主要的执行上下文是接收来自用户的 HTTP 请求的上下文。在这种上下文中阻塞线程是不好的,因为您可以轻松耗尽执行上下文并影响与doSomething 无关的请求。

    Play docs 对阻塞代码可能出现的问题有更好的解释:

    如果您计划编写阻塞 IO 代码,或可能执行大量 CPU 密集型工作的代码,您需要确切知道哪个线程池正在承受该工作负载,并且需要相应地对其进行调整。 在不考虑这一点的情况下进行阻塞 IO 可能会导致 Play 框架的性能非常差,例如,您可能会看到每秒仅处理几个请求,而 CPU 使用率为 5%。相比之下,典型开发硬件(例如 MacBook Pro)上的基准测试表明,如果调整正确,Play 能够处理每秒数百甚至数千个请求的工作负载。

    在您的情况下,这两种方法都是使用 Play 默认线程池执行的。我建议你看一下recommended best practices,看看你是否需要不同的执行上下文。我还建议您阅读有关 DispatchersFutures 的 Akka 文档,以更好地了解执行 Future 的内容以及阻塞/非阻塞代码。

    【讨论】:

      【解决方案2】:

      如果您在第二种方法中使用不同的execution contexts,这种方法是有意义的。

      例如,有一个用于响应请求,另一个用于阻止请求。 因此,您可以使用普通的 playExecutionContext 来保持应用程序的运行和应答,并将 blocking 操作分离到另一个操作中。

      def doSomething2(): Future[Boolean] = Future{ 
          blocking { blockService.block() }
      }( mySpecialExecutionContextForBlockingOperations )
      

      更多信息:http://docs.scala-lang.org/overviews/core/futures.html#blocking

      【讨论】:

      • 是的,如果我使用 2 个不同的执行上下文确实有意义,但如果不是,这真的没有任何意义,对吧?
      【解决方案3】:

      你是对的。我在 doSomething1 中看不到任何意义。它只是使调用者的接口复杂化,而没有提供异步 API 的好处。

      【讨论】:

        【解决方案4】:

        BlockService 是否处理阻塞操作?
        通常情况下,使用blocking,正如@Andreas 提醒的那样,对另一个线程进行阻塞操作是有意义的。

        【讨论】:

          猜你喜欢
          • 2015-11-08
          • 1970-01-01
          • 2013-04-03
          • 1970-01-01
          • 1970-01-01
          • 2015-09-22
          • 1970-01-01
          • 2016-01-18
          • 2017-08-17
          相关资源
          最近更新 更多