A Future
получает право на выполнение, как только оно создано. Таким образом, эта строка создает два Futures
, которые потенциально могут быть выполнены:
val futureOperations = Seq(doOne(), doTwo())
Вызов Future.sequence
создаст новый Future
, который ждет для каждого из фьючерсов на завершить по очереди, но они оба уже будут доступны для выполнения к этому моменту в коде.
val res = Future.sequence(futureOperations)
Если вы хотите, чтобы Future
с запускали последовательно, вам нужно использовать map/flatMap
:
val res = doOne().map( _ => doTwo())
С этим кодом doTwo
не будет вызываться до тех пор, пока не завершится doOne
(и вовсе не произойдет сбой doOne
)
Причина, по которой этого не происходит похоже, что в вашем примере это то, что вы вызываете блокирующую операцию в Future
, которая блокирует поток, который в противном случае использовался бы для выполнения других Future
s. Таким образом, хотя для выполнения доступно два Future
, на самом деле выполняется только один.
Если вы пометите код как blocking
, он будет работать правильно:
import scala.concurrent.blocking
def doOne(): Future[Unit] = Future {
blocking{println("startFirst"); Thread.sleep(3000); println("stop First")}
}
def doTwo(): Future[Unit] = Future {
blocking{println("startSecond"); Thread.sleep(1000); println("stop Second")}
}
См. Раздел комментариев для подробностей того, почему поведение по умолчанию отличается в разных версиях, и почему вы никогда не должны делать предположений относительно относительного порядка выполнения независимых Future
s.