如何为期货配置微调线程池?


80

Scala的期货线程池有多大?

我的Scala应用程序产生了数以百万计的future {}s,我想知道是否可以通过配置线程池来优化它们。

谢谢。


Slick 3.0使用自己的连接和线程池,所以当它管理自己的线程池时,为什么我们需要提供隐式的执行
上下文来平滑

1
@RahulGulabani,摘自“基本浮油”书:The reason is that map, flatMap methods of Action allows you to call arbitrary code when joining the actions together. Slick cannot allow that code to be run on its own execution context, because it has no way to know if you are going to tie up Slicks threads for a long time.
srzhio

Answers:


90

您可以指定自己的期货将在其中运行的ExecutionContext,而不是导入全局隐式ExecutionContext。

import java.util.concurrent.Executors
import scala.concurrent._

implicit val ec = new ExecutionContext {
    val threadPool = Executors.newFixedThreadPool(1000)

    def execute(runnable: Runnable) {
        threadPool.submit(runnable)
    }

    def reportFailure(t: Throwable) {}
}

72
很好的答案,您可以通过使用ExecutionContext上的帮助程序方法来减少样板,这些方法可以让您直接从给定的Executor实例化。例如,隐式val ec = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(10))
sksamuel

1
当然,这一切都很好,但是对implicits.global的线程是否有真正的限制?如果是这样,是否可以通过application.conf像akka一样进行配置?
尼克

6
@Nick是的,implicits.global每个CPU内核只有1个线程。最适合CPU绑定任务。但是对于经典的阻塞IO(例如jdbc),这是性能上的灾难。
Ben Hutchison 2014年

2
我需要在使用此函数后添加一个调用来关闭线程池,否则程序将永不终止... def shutdown()=
threadPool.shutdown

2
为什么在“正常”情况下关闭它,而在将隐式设置为其他值时却不关闭呢?
hbogert 2015年

152

该答案来自monkjack,是已接受答案的评论。但是,您可能会错过这个好答案,因此我将其重新张贴在这里。

implicit val ec = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(10))

如果只需要更改线程池数,则只需使用全局执行程序并传递以下系统属性即可。

-Dscala.concurrent.context.numThreads=8 -Dscala.concurrent.context.maxThreads=8

2
这是一个更优雅的解决方案
Ben Hutchison

我尝试了两个值均为5的情况,但我仍然看到多达8个线程同时运行。
micseydel

3

在Scala期货中指定线程池的最佳方法:

implicit val ec = new ExecutionContext {
      val threadPool = Executors.newFixedThreadPool(conf.getInt("5"));
      override def reportFailure(cause: Throwable): Unit = {};
      override def execute(runnable: Runnable): Unit = threadPool.submit(runnable);
      def shutdown() = threadPool.shutdown();
    }

0
class ThreadPoolExecutionContext(val executionContext: ExecutionContext)

object ThreadPoolExecutionContext {

  val executionContextProvider: ThreadPoolExecutionContext = {
    try {
      val executionContextExecutor: ExecutionContextExecutor = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(25))
      new ThreadPoolExecutionContext(executionContextExecutor)
    } catch {
      case exception: Exception => {
        Log.error("Failed to create thread pool", exception)
        throw exception
      }
    }
  }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.