Як налаштувати тонко налаштований пул потоків для ф’ючерсів?


80

Наскільки великий пул потоків Scala для ф’ючерсів?

Мій додаток Scala робить багато мільйонів future {}с, і мені цікаво, чи можу я щось зробити для їх оптимізації, налаштувавши пул потоків.

Дякую.


Slick 3.0 використовує власне підключення та пул потоків, так чому нам потрібно надавати неявний контекст виконання для slick, коли він управляє власним пулом потоків
Рахул Гулабані,

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

Відповіді:


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) {}
}

73
Чудова відповідь, ви можете трохи зменшити шаблон, використовуючи допоміжні методи на ExecutionContext, які дозволяють створювати екземпляри безпосередньо від даного виконавця. Наприклад, неявний val ec = ExecutionContext.fromExecutor (Executors.newFixedThreadPool (10))
sksamuel

1
Звичайно, це все приємно, але чи існує реальна межа в потоках на implicits.global? Якщо так, чи можна це налаштовувати як akka через application.conf?
Нік

6
@ Нік так, implicits.global - це лише 1 потік на ядро ​​процесора. Оптимальний для завдань, пов’язаних з процесором. Але для класичного блокування вводу-виводу (наприклад, jdbc) це катастрофа продуктивності.
Бен Хатчісон,

2
Мені потрібно було додати виклик для вимкнення пулу потоків після використання цього, або програма ніколи не припиняє ... def shutdown () = threadPool.shutdown ()
justinhj

2
Чому він вимикається у "звичайному" випадку, але не коли ми встановлюємо неявне щось інше?
hbogert

152

Ця відповідь від monkjack, коментар прийнятої відповіді. Однак можна пропустити цю чудову відповідь, тому я розміщую її тут.

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

Якщо вам просто потрібно змінити кількість пулів потоків, просто використовуйте глобальний виконавець і передайте наступні властивості системи.

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

2
це більш елегантне рішення
Бен Хатчісон

Я спробував обидва з значенням 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
      }
    }
  }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.