Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/352.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Scala和第三方Java库中使用Akka的最佳实践_Java_Scala_Asynchronous_Concurrency_Akka - Fatal编程技术网

在Scala和第三方Java库中使用Akka的最佳实践

在Scala和第三方Java库中使用Akka的最佳实践,java,scala,asynchronous,concurrency,akka,Java,Scala,Asynchronous,Concurrency,Akka,我需要在Scala/Akka代码中使用。此API为您提供了同步和异步方法。异步的返回。这里有一个关于在Scala中处理Java期货的问题。但就我而言,我有两个选择: 将来使用同步API和包装阻塞代码并标记阻塞: Future { blocking { cache.get(key) //synchronous blocking call } } 使用异步JavaAPI,每n毫秒对Java Future进行一次轮询,以检查Future是否完成(如上面链接问题中的一个答案所述)

我需要在Scala/Akka代码中使用。此API为您提供了同步和异步方法。异步的返回。这里有一个关于在Scala中处理Java期货的问题。但就我而言,我有两个选择:

  • 将来使用同步API和包装阻塞代码并标记阻塞:

    Future {
      blocking {
        cache.get(key) //synchronous blocking call
      } 
    }
    
  • 使用异步JavaAPI,每n毫秒对Java Future进行一次轮询,以检查Future是否完成(如上面链接问题中的一个答案所述)


  • 哪一个更好?我倾向于第一种选择,因为投票会极大地影响响应时间。
    blocking{}
    block不应该阻止阻塞整个池吗?

    我总是选择第一个选项。但是我用了一种稍微不同的方式。我不使用
    阻塞
    功能。(实际上我还没有考虑过。)相反,我为将来提供了一个定制的执行上下文,它封装了同步阻塞调用。所以它看起来基本上是这样的:

    val ecForBlockingMemcachedStuff = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(100)) // whatever number you think is appropriate
    // i create a separate ec for each blocking client/resource/api i use
    
    Future {
        cache.get(key) //synchronous blocking call
    }(ecForBlockingMemcachedStuff) // or mark the execution context implicit. I like to mention it explicitly.
    
    因此,所有的阻塞调用都将使用专用的执行上下文(=线程池)。因此,它与负责非阻塞内容的主执行上下文分离

    Typesafe提供的示例中也解释了这种方法。第4课中有一个关于如何处理阻塞呼叫的视频。Nilanjan Raychaudhuri(希望我拼写正确)对此进行了解释,他是Scala书籍的著名作者

    更新:我有一个问题。他解释了
    阻塞
    方法与自定义
    执行上下文
    之间的区别。
    阻塞
    功能只是创建一个特殊的
    执行上下文
    。对于需要多少线程的问题,它提供了一种简单的方法。每当池中所有其他现有线程都忙时,它都会生成一个新线程。因此,它实际上是一个不受控制的执行上下文。它可能会创建大量线程并导致问题,如内存不足错误。因此,使用自定义执行上下文的解决方案实际上更好,因为它使这个问题变得显而易见。Nilanjan还补充说,您需要考虑电路断开的情况,因为这个池被请求过载。

    TLDR:是的,阻止通话很糟糕使用自定义/专用ExecutionContext阻止调用。还考虑了电路中断。< /强>

    < P>对如何处理阻塞调用提供了一些建议:

    在某些情况下,进行阻塞操作是不可避免的,即 一个线程在不确定的时间内休眠,等待外部消息 要发生的事件。例如传统的RDBMS驱动程序或消息传递API, 根本原因通常是(网络)I/O发生在 封面。面对这种情况时,您可能会试图将 在将来阻止调用并使用它,但是 策略太简单了:你很可能会发现瓶颈或问题 当应用程序运行时,内存或线程不足 装载

    关于“阻塞”的充分解决方案的非详尽清单 “问题”包括以下建议:

    • 在参与者(或路由器管理的一组参与者)内执行阻塞调用,确保配置线程池 专用于此目的或尺寸足够大

    • 在将来进行阻塞调用,确保在任何时间点(提交无限制的 这种性质的任务数量将耗尽您的内存或线程 限制)

    • 在将来执行阻塞调用,为线程池提供适用于 运行应用程序的硬件

    • 指定一个线程来管理一组阻塞资源(例如,驱动多个通道的NIO选择器),并在事件发生时进行调度 作为参与者消息出现

    第一种可能性特别适合于 本质上是单线程的,就像数据库句柄 传统上一次只能执行一个未完成的查询并使用 内部同步以确保这一点。一个常见的模式是创建 用于N个参与者的路由器,每个参与者封装一个DB连接和 处理发送到路由器的查询。然后必须调整数字N 对于最大吞吐量,这将根据所使用的DBMS而有所不同 部署在什么硬件上


    是的,我认为这是第三种方法。我只是想知道我是否可以结合使用自定义执行上下文和
    阻塞
    功能。我在某个地方读到,如果使用自定义执行上下文,则此功能无效,因此在悲观场景中,可以阻止自定义池。