flatMap
или map
- это последовательные операции над Scala Future и сами по себе не имеют ничего общего с параллельным запуском вещей. Их можно рассматривать как простые обратные вызовы, выполняемые после завершения Future. Другими словами, предоставленный код внутри map(...)
или flatMap(...)
начнет выполняться только после завершения предыдущего Future.
zip
, с другой стороны, будет запускать ваши Futures параллельно и возвращать результат как кортеж, когда оба они завершены. Точно так же вы можете использовать zipWith
, который принимает функцию для преобразования результатов двух Futures (объединяет операции zip и map):
mergeSortParallel0(left).zipWith(mergeSortParallel0(right)){
case (sortedLeft, sortedRight) => merge(sortedLeft, sortedRight)
}
Другой способ добиться параллелизма - объявить Futures за пределами for-понимания. Это работает, поскольку фьючерсы в Scala являются «нетерпеливыми», и они запускаются, как только вы их объявляете (присваиваете val
):
def mergeSortParallel0[T: Ordering](items: IndexedSeq[T]): Future[IndexedSeq[T]] = {
if (items.length <= 16) Future.successful(mergeSortSequential(items))
else {
val (left, right) = items.splitAt(items.length / 2)
val leftF = mergeSortParallel0(left)
val rightF = mergeSortParallel0(right)
for {
sortedLeft <- leftF
sortedRight <- rightF
} yield {
merge(sortedLeft, sortedRight)
}
}
}